[PYTHON] How to make a shooting game with toio (Part 1)

I will be at the Tsukuba Mini Maker Faire

I made it with toio! Tomo no Kai (Unofficial), Mr. Kato applied for TMMF2020 and won! Because of the relationship, I will also participate. Tokyo Maker Faire has participated as a guest several times, but this story is where I wanted to exhibit someday! (Around the end of January 2020), this has to jump.

Click here for the second part

Out of material

Although we were able to exhibit, we hadn't decided what to put out. As for what I have, I made it with toio! Tomo no Kai (Unofficial) announced at the LT meeting "toio de Bundodo ”,“ Turn toio 3 times faster ”, but I want to make new material anyway. However, since this is the first time for us to exhibit, it is no good if we try too much technically and fail, or if it is not completed by the day of the exhibition. So I decided to think with the following concept.

In particular, the motor control command that specifies the target value coordinates of the new function does not require the rotation control of the motor while constantly monitoring the position of the mat on the host side as in the past, so the amount of BLE communication between the toio core cube and the host Can be expected to be reduced. In an environment like Maker Faire where 2.4GHz band wireless communication is likely to be crowded, it contributes to stable operation, and above all, it improves battery life.

I wanted to make it look like a game for children to play, so I decided to make it as simple as shooting a moving toio core cube with something like a gun and defeating it. Put something like -like (</ rp> Mato </ rt> ) </ rp> </ ruby> on the toio core cube with Lego. Is to be shot.

Equipment configuration

Since the device configuration is built-in BLE as a host machine, Raspberry Pi 3B (hereinafter abbreviated as RasPi) is used, RasPi and notebook PC are directly connected by wired LAN, fixed IP address is assigned, and tera from the notebook PC side. I assumed that I logged in with ssh from term etc. to start and end the program. I could have attached something like a start button to the RasPi to run it, but I thought there would be various troubles, so I simply logged in and let a human run the program. In addition, the RasPi is equipped with a Speaker pHat for sound effect output and an LCD2 USB module for displaying scores and status.

system.png

Survey, implementation

Motor control command for specifying target value coordinates

Anyway, [[Motor control command to specify target value coordinates](https://toio.github.io/toio-spec/docs/ble_motor#%E7%9B] added in toio core cube firmware ver.2 % AE% E6% A8% 99% E6% 8C% 87% E5% AE% 9A% E4% BB% 98% E3% 81% 8D% E3% 83% A2% E3% 83% BC% E3% 82% BF Let's look at% E3% 83% BC% E5% 88% B6% E5% BE% A1). According to the specifications, there are the following two types.

This time, the target toio core cube is a runaway movement (as a movement [Galaga](https://ja.wikipedia.org/wiki/%E3%82%AE%E3%83%A3%E3%83%] A9% E3% 82% AC), [Gaplus](https://ja.wikipedia.org/wiki/%E3%82%AE%E3%83%A3%E3%83%97%E3%83%A9% E3% 82% B9) I wanted to make the movement to form a formation immediately after the game started), so the second "[Specify multiple target coordinates Motor control type 0x04](https://toio.github. io / toio-spec / docs / ble_motor #% E8% A4% 87% E6% 95% B0% E7% 9B% AE% E6% A8% 99% E6% 8C% 87% E5% AE% 9A% E4% BB % 98% E3% 81% 8D% E3% 83% A2% E3% 83% BC% E3% 82% BF% E3% 83% BC% E5% 88% B6% E5% BE% A1) "is more suitable for use. It seems to fit. It seems to move to move by sewing multiple target coordinates in order.

Try to move

"[Specify multiple target coordinates Motor control type 0x04](https://toio.github.io/toio-spec/docs/ble_motor#%E8%A4%87%E6%95%B0%E7%9B%AE%" E6% A8% 99% E6% 8C% 87% E5% AE% 9A% E4% BB% 98% E3% 81% 8D% E3% 83% A2% E3% 83% BC% E3% 82% BF% E3% In order to confirm the actual movement of "83% BC% E5% 88% B6% E5% BE% A1)", I made it with toio! Tomo no Kai (Unofficial) The python library tomotoio used in the LT meeting demo. (tomotoio / tree / master / tomotoio) is modified a little so that it can output type 0x04 motor control packets.

tomotoio/cube.Add a method like this to py's Cube class
def setMotor4(self, ctrlid: int, goals, writemode:int, timeout: int = 0, movingtype: int = 0, maxspeed: int = 0, speedtype: int =0):

The name is "setMotor4 ()" without any twist. Well, all you have to do is specify multiple destination positions (x, y, Θ) for goals, encode it into a 0x04 motor-controlled packet, and send it. "[Specify multiple target coordinates Motor control type 0x04](https://toio.github.io/toio-spec/docs/ble_motor#%E8%A4%87%E6%95%B0%E7%9B%AE%" E6% A8% 99% E6% 8C% 87% E5% AE% 9A% E4% BB% 98% E3% 81% 8D% E3% 83% A2% E3% 83% BC% E3% 82% BF% E3% According to "83% BC% E5% 88% B6% E5% BE% A1)", it is possible to specify up to 29 target positions, so if you can specify that many positions, you can move it in a complicated trajectory. is.

Motion creation

Since it is possible to specify multiple positions, it is necessary to create an array of positions to move along that position. However, there is no elegant way to calculate all the positions of complicated orbits mathematically (I skipped mathematics ...), so humans specify the positions by hand. I wrote a script that reads the coordinates when the toio core cube is pressed firmly on the mat and the bottom button is on, sends it to the host side, records the coordinates in order on the host side, and then dumps it in text. Use it to take some coordinates of the points on the orbit you want to move. This time, I plan to move the two toio core cubes at the same time to escape, but I will manually create a trajectory where the two toio core cubes are likely to collide and do not collide.

座標を拾う Spread the coordinates at several points according to the trajectory you want to move. If you specify to move while changing direction instead of moving to the next after changing direction, the orbit will not be linear but will be curved to some extent.

Multiple destination designation does not work

I put the created coordinate array in setMotor4 () and tried to move it, but it doesn't work. I wondered why, and when it was RasPi (raspbian) BLE communication, the MTU had a standard size of 23 octets and a real payload of only 20 octets. It turned out that the cause seems to be not being done. Depending on the system, it seems that the MTU size of BLE is increased and communication can be performed with a length exceeding 23 octets, but even if I tried various things with RasPi, it was not good at all. We don't have much time to go live, so we'll give up on MTU size expansion and switch to something we can do with 20 octets. In the range of 20 octets, only 2 sets of destination coordinates can be entered. Fortunately, when the toio core cube reaches the target coordinates, notify will fly, and it was a specification that the destination coordinates can be additionally loaded even while moving.

  1. At first, stack the coordinates for 2 pieces
  2. When notify arrives that the toio core cube has reached the first coordinate, add one third coordinate.
  3. Repeat step 2. 複数目的位置指定.png

I implemented it by the method. With this, we were able to realize the movement of sewing multiple coordinates in succession. After that, while putting the array of coordinates collected earlier and actually moving the toio core cube, adjust the parameters of the speed value and speed type (such as gradually increasing the speed) so that it moves like that.

Hit judgment and what to shoot

I shoot the target toio core cube, but I thought that the following three could be used as a hit judgment and tried it.

I haven't decided why to shoot the toio core cube (above the target) in the first place, but somehow nerf, [Rubber band gun](https: / /www.amazon.co.jp/gp/product/B07PJPBGDL/), Air Gun I was vaguely thinking However, the drawing of the exhibition space was disclosed (2020/1/24), and when I looked at it, it was a table with a width of 180 cm and a depth of 45 cm. It is very small because other people will also be exhibited. It turns out that there is almost no distance to shoot. Since you will shoot from a close range, nerf is too powerful and if you hit it, the target made with Lego will be disjointed, so it is useless. Cylinder type air gun is more difficult to aim than I expected and it is very troublesome because it is a single shot. As a result, I decided to use a continuous rubber band gun. 輪ゴム鉄砲1輪ゴム鉄砲2

When I tried collision detection, horizontal detection, and attitude detection of the motion sensor while actually shooting with a rubber band gun, the toio core cube did not fall down to the extent that it hit the rubber band. Therefore, posture detection is not adopted. It is tested whether the vibration per rubber band can be discriminated by collision detection and horizontal detection. I adjusted the angle threshold for horizontal detection and the threshold for collision detection in various ways, and in the end I decided to use only collision detection. However, it was found that this threshold value changes depending on the weight of what is placed on the toio core cube, so it was necessary to set a value that matches the target. Also, with this method, there is a problem that even if toio core cubes collide with each other, it will be a hit judgment, but it is difficult to control the trajectory so that they do not collide, so this time I will close my eyes. I made it.

Target and direction

I intended to make a target with LEGO, but it is useless to make it too large, so as a result of my thoughts, [LEGO Minecraft](https://www.amazon.co.jp/%E3%83%AC%E3%82] % B4-LEGO-30393-% E3% 83% 9E% E3% 82% A4% E3% 83% B3% E3% 82% AF% E3% 83% A9% E3% 83% 95% E3% 83% 88- % E3% 82% B9% E3% 83% 86% E3% 82% A3% E3% 83% BC% E3% 83% 96% E3% 81% A8% E3% 82% AF% E3% 83% AA% E3 % 83% 83% E3% 83% 91% E3% 83% BC / dp / B07NDXJNPH / ref = pd_aw_sbs_21_1 / 356-7905405-7675543? _Encoding = UTF8 & pd_rd_i = B07NDXJNPH & pd_rd_r = 5c498ac2-34c2-44c7-b449-bc = bff3a3a6-0f6e-4187-bd60-25e75d4c1c8f & pf_rd_r = BSHJKFDE63WHGZ46HVZM & psc = 1 & refRID = BSHJKFDE63WHGZ46HVZM]) has been adopted. You can add a story to defeat the creeper that runs around, and it is a plan that will be popular with elementary school students. LEGO MINECRAFTの的

Since the target has been decided, adjust the threshold value of impact detection according to the weight and adjust the speed so that it accelerates or decelerates while moving along the trajectory according to the coordinate arrangement. If you stop or change direction too suddenly, it will be treated as an impact and it will be a "hit", so adjust it to a moderate speed. Also, when it is "hit", it expresses that it hits by spinning for a few seconds. During this time, we have added ad hoc measures such as preventing it from being treated as a "hit" even if it hits again.

I wanted to make a sound effect when "hit", so I had Pimoroni's Speaker pHat at hand, so I incorporated it into RasPi. I tried to make it ring. Select the sound source from the free material site "Sound Effect Lab" and select the sound effect "Boyoyon". I used pygame for playback on python. ("Read and play sound with Pygame")

Score display

When it became a "hit", I wanted to add the score and display the score somewhere, but I thought that it was too normal to connect an HDMI display normally and it was boring, so I got it at Tokyo Maker Faire PIXOO I tried to display it, but I gave up because I couldn't reach the control of RasPi with bluetooth. I happened to have a character display LCD module with LCD2USB specifications, so I changed it to display it instead. Well, in production, the player didn't see the score at all, but it was convenient for me to start / end the script and see the status. Speaker pHatとLCD2USB

USB port 1602 LCD Module for Pi (LCD2USB) Python library for LCD2USB https://pypi.org/project/lcd2usb/

Game content

Addition of easy mode

Although it is close to aiming at the target to move around, I thought it would be difficult for younger children, so I decided to make a simple mode as well. The target is to stand still, and when it hits, it expresses "hit" and then quickly moves to another place and stops.

[Easy mode stops and moves to another position when hit](http://www.youtube.com/watch ? v = OX2hYu_99j0)

It ends when you hit it several times.

A little messy mode

The target moves around as soon as the game starts. It is moving along a fixed orbit, but at a glance, it feels like it is running away at random. Points will be added when the rubber band hits, and it will end when all the predetermined movement patterns have been completed.

[A little messy mode moves around](http://www.youtube.com/watch?v=Su- xKABGDyg)

I intended to adjust the position and speed of the orbits of each of the two toio core cubes so that they would not collide with each other, but if one of them stopped in the hit state, the running timing would shift and a collision would occur somewhere. There are times, but I decided not to care.

Each game relaunches the script once. While looking at the age of the customer, select whether it is easy or a little messy to start.

I managed to get it into shape

I made various adjustments and managed to get it working on 2/14 the day before the production. kouji_tokkankouji.png

Continued to Part 2

Recommended Posts

How to make a shooting game with toio (Part 1)
How to make a simple Flappy Bird game with pygame
How to make a dictionary with a hierarchical structure.
I want to make a game with Python
How to make a Japanese-English translation
How to make a crawler --Advanced
How to make a recursive function
How to make a deadman's switch
[Blender] How to make a Blender plugin
How to make a crawler --Basic
How to authenticate with Django Part 2
How to authenticate with Django Part 3
How to make a Cisco Webex Teams BOT with Flask
How to make a multiplayer online action game on Slack
How to make a hacking lab-Kali Linux (2020.1) VirtualBox 64-bit Part 2-
Let's make a shiritori game with Python
How to add a package with PyCharm
[Python] How to make a class iterable
How to make a command to read the configuration file with pyramid
How to make a surveillance camera (Security Camera) with Opencv and Python
[Cocos2d-x] How to make Script Binding (Part 2)
How to make a unit test Part.1 Design pattern for introduction
How to make a Backtrader custom indicator
How to make a Pelican site map
[Cocos2d-x] How to make Script Binding (Part 1)
How to make a dialogue system dedicated to beginners
How to read a CSV file with Python 2/3
How to send a message to LINE with curl
A memorandum to make WebDAV only with nginx
How to draw a 2-axis graph with pyplot
[Python] Make a game with Pyxel-Use an editor-
How to develop a cart app with Django
Try to make a "cryptanalysis" cipher with Python
How to make a QGIS plugin (package generation)
[Python] Make a simple maze game with Pyxel
How to measure execution time with Python Part 1
I read "How to make a hacking lab"
Try to make a dihedral group with Python
How to create a multi-platform app with kivy
How to make Linux compatible with Japanese keyboard
I tried to make a ○ ✕ game using TensorFlow
How to measure execution time with Python Part 2
Make a squash game
Make a Tetris-style game!
A new form of app that works with GitHub: How to make GitHub Apps
How to convert / restore a string with [] in python
[Python] How to draw a line graph with Matplotlib
Try to make a command standby tool with python
Explain in detail how to make sounds with python
How to create a submenu with the [Blender] plugin
How to get a logged-in user with Django's forms.py
How to convert a class object to a dictionary with SQLAlchemy
Let's make a simple game with Python 3 and iPhone
How to make unit tests Part.2 Class design for tests
Make a function to describe Japanese fonts with OpenCV
How to upload with Heroku, Flask, Python, Git (Part 1)
How to make a Python package using VS Code
How to make an HTTPS server with Go / Gin
How to upload with Heroku, Flask, Python, Git (Part 2)
Basics of PyTorch (2) -How to make a neural network-
[Python] How to create a 2D histogram with Matplotlib