Created
August 27, 2019 10:14
-
-
Save deviceplususer/59c4b0c2e73ba07a39e3a863fcb4ca36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define WIDTH 5//LEDの横の数 | |
#define HEIGHT 5//LEDの縦の数 | |
#define LED_PIN 6//LEDテープの信号線 | |
#define INTERVAL 750//画面切り替えのインターバル | |
#define MAX_BRIGHTNESS 32//動植物の最大の明るさ | |
#define ANIMAL_MAX_NUM 10//動物の最大数 | |
#define ANIMAL_DECREASE 1//動物の体力減少 | |
#define GRASS_GROWTH_NUM 3//同時に草が成長する箇所 | |
#define GRASS_GROWTH_POTENTIAL 2//草が成長するスピード | |
#define KNOCK_THRESHOLD 5000//ノックと判断する閾値 | |
#include <MsTimer2.h> | |
#include <Adafruit_NeoPixel.h> | |
#include <Wire.h> | |
#include <Adafruit_LIS3DH.h> | |
#include <Adafruit_Sensor.h> | |
struct RGB | |
{ | |
int r; | |
int g; | |
int b; | |
}; | |
struct Animal | |
{ | |
float x; | |
float y; | |
int life; | |
bool isDead; | |
RGB color; | |
}; | |
// LED | |
Adafruit_NeoPixel pixels;//LEDをコントロールするオブジェクト | |
int ledMatrix[WIDTH][HEIGHT];//LEDの配置と番号を記録する2次元配列 | |
int grassMatrix[WIDTH][HEIGHT];//草の育成を保持する2次元配列 | |
Animal animals[ANIMAL_MAX_NUM];//動物の情報を保持する配列 | |
//加速度センサー | |
Adafruit_LIS3DH lis = Adafruit_LIS3DH();//加速度センサーをコントロールするオブジェクト | |
long px, py, pz;//1フレーム前の加速度 | |
boolean bornFlag;//次のフレームで生物が誕生するかのフラグ | |
void setup() | |
{ | |
Serial.begin( 9600 ); | |
randomSeed( analogRead(0) ); | |
// TIMER ------------------------- | |
MsTimer2::set(INTERVAL, update);//関数updateを一定間隔ごとに呼び出すタイマー | |
MsTimer2::start(); | |
// NEOPIXEL -------------------- | |
pixels = Adafruit_NeoPixel(WIDTH * HEIGHT, LED_PIN, NEO_GRB + NEO_KHZ800);//NeoPixelオブジェクトを生成 | |
pixels.begin(); | |
// ACC SENSOR ------------------------ | |
if (! lis.begin(0x18)) { | |
while (1); | |
} | |
lis.setRange(LIS3DH_RANGE_2_G);//加速度センサーの感度を設定。2, 4, 8, 16G | |
// LED MATRIX ------------------------- | |
//0~24番のLEDをX, Yの座標に置き換える | |
ledMatrix[0][0] = 0;//0番のLEDは、x=0, y=0 | |
ledMatrix[1][0] = 9;//9番のLEDは、x=1, y=0 | |
ledMatrix[2][0] = 10; | |
ledMatrix[3][0] = 19; | |
ledMatrix[4][0] = 20; | |
ledMatrix[0][1] = 1; | |
ledMatrix[1][1] = 8; | |
ledMatrix[2][1] = 11; | |
ledMatrix[3][1] = 18; | |
ledMatrix[4][1] = 21; | |
ledMatrix[0][2] = 2; | |
ledMatrix[1][2] = 7; | |
ledMatrix[2][2] = 12; | |
ledMatrix[3][2] = 17; | |
ledMatrix[4][2] = 22; | |
ledMatrix[0][3] = 3; | |
ledMatrix[1][3] = 6; | |
ledMatrix[2][3] = 13; | |
ledMatrix[3][3] = 16; | |
ledMatrix[4][3] = 23; | |
ledMatrix[0][4] = 4; | |
ledMatrix[1][4] = 5; | |
ledMatrix[2][4] = 14; | |
ledMatrix[3][4] = 15; | |
ledMatrix[4][4] = 24; | |
reset(); | |
} | |
void loop() | |
{ | |
checkKnock();//ノックされたかどうか判断する | |
delay(1); | |
} | |
void update() | |
{ | |
// GRASS ---------------------------------------- | |
grawGrass();//草が育つ | |
// ANIMAL ---------------------------------------- | |
for ( int i = 0; i < ANIMAL_MAX_NUM; i++) | |
{ | |
if ( !animals[i].isDead ) | |
{ | |
moveMaxGrass(i);//一番大きな草に向かって移動 | |
//現在地の草を食べて体力回復 | |
animals[i].life += grassMatrix[int(animals[i].x)][int(animals[i].y)]; | |
grassMatrix[int(animals[i].x)][int(animals[i].y)] = 0; | |
//体力減少 | |
animals[i].life -= ANIMAL_DECREASE; | |
//体力が0になったら死亡 | |
if ( animals[i].life <= 0 ) | |
{ | |
animals[i].life = 0; | |
animals[i].isDead = true; | |
} | |
//体力が上限になったら増える | |
if ( animals[i].life > MAX_BRIGHTNESS ) | |
{ | |
animals[i].life = MAX_BRIGHTNESS / 2; | |
bornAnimal(i); | |
} | |
} | |
} | |
// KNOCK ---------------------------------------- | |
// 加速度センサーが反応していれば、動物を増やす | |
if ( bornFlag ) | |
{ | |
bornFlag = false; | |
bornAnimal(-1); | |
} | |
// OUTPUT ---------------------------------------- | |
setLed();//LEDに値をセットし、光らせる | |
} | |
void reset() | |
{ | |
// ANIMAL ------------------------------------- | |
for ( int i = 0; i < ANIMAL_MAX_NUM; i++) | |
{ | |
animals[i].x = random(WIDTH); | |
animals[i].y = random(HEIGHT); | |
animals[i].life = 10; | |
animals[i].color.r = random(0, 10); | |
animals[i].color.g = random(0, 10); | |
animals[i].color.b = random(0, 10); | |
animals[i].isDead = true; | |
} | |
// GRASS ------------------------------------- | |
for ( int y = 0; y < HEIGHT; y++) | |
{ | |
for ( int x = 0; x < WIDTH; x++) | |
{ | |
grassMatrix[x][y] = 0; | |
} | |
} | |
// LED ------------------------------------- | |
pixels.clear(); | |
pixels.show(); | |
} | |
void grawGrass() | |
{ | |
for ( int i = 0; i < GRASS_GROWTH_NUM; i++) | |
{ | |
int rndX = random(WIDTH); | |
int rndY = random(HEIGHT); | |
grassMatrix[rndX][rndY] += random(GRASS_GROWTH_POTENTIAL + 1); //ランダムな場所の草が成長する | |
if ( grassMatrix[rndX][rndY] > MAX_BRIGHTNESS ) grassMatrix[rndX][rndY] = MAX_BRIGHTNESS; | |
} | |
} | |
void moveMaxGrass( int _id ) | |
{ | |
// 最も成長している草の位置を調べる | |
int maxGrass = 0; | |
int maxGrassX = 0; | |
int maxGrassY = 0; | |
for ( int y = 0; y < HEIGHT; y++) | |
{ | |
for ( int x = 0; x < WIDTH; x++) | |
{ | |
if ( grassMatrix[x][y] > maxGrass ) | |
{ | |
maxGrass = grassMatrix[x][y]; | |
maxGrassX = x; | |
maxGrassY = y; | |
} | |
} | |
} | |
// 目標と比較して近づく | |
int nX = animals[_id].x; | |
int nY = animals[_id].y; | |
if ( (maxGrassX - animals[_id].x) > 0 ) | |
{ | |
nX += 1; | |
} else if ( (maxGrassX - animals[_id].x) < 0 ) | |
{ | |
nX -= 1; | |
} | |
if ( (maxGrassY - animals[_id].y) > 0 ) | |
{ | |
nY += 1; | |
} else if ( (maxGrassY - animals[_id].y) < 0 ) | |
{ | |
nY -= 1; | |
} | |
//移動先に生きている動物がいたら、移動しない | |
for ( int i = 0; i < ANIMAL_MAX_NUM; i++ ) | |
{ | |
if ( animals[i].x == nX && animals[i].y == nY )//XY両方とも一致している | |
{ | |
if ( !animals[i].isDead )//生存している | |
{ | |
if ( i != _id) //自分自身ではない | |
{ | |
return;//関数を終わる | |
} | |
} | |
} | |
} | |
animals[_id].x = nX; | |
animals[_id].y = nY; | |
} | |
void bornAnimal(int _parent) | |
{ | |
int x; | |
int y; | |
int r; | |
int g; | |
int b; | |
//枠の空きを探す | |
for ( int i = 0; i < ANIMAL_MAX_NUM; i++) | |
{ | |
if ( animals[i].isDead ) | |
{ | |
if ( _parent < 0 )//振動で生まれた場合 | |
{ | |
x = WIDTH / 2; | |
y = HEIGHT / 2; | |
r = random(0, 15); | |
g = random(0, 15); | |
b = random(0, 15); | |
} else {//親がいる場合 | |
x = animals[ _parent ].x; | |
y = animals[ _parent ].y; | |
r = animals[ _parent ].color.r; | |
g = animals[ _parent ].color.g; | |
b = animals[ _parent ].color.b; | |
} | |
animals[i].x = x; | |
animals[i].y = y; | |
animals[i].life = 10; | |
animals[i].color.r = r; | |
animals[i].color.g = g; | |
animals[i].color.b = b; | |
animals[i].isDead = false; | |
break;//ループを抜ける | |
} | |
} | |
} | |
void checkKnock() { | |
lis.read();//センサーの値を読み取り | |
long delta = abs(px - lis.x) + abs(py - lis.y) + abs(pz - lis.z);//各軸の変化量の合計 | |
if ( delta > KNOCK_THRESHOLD )//変化量が大きければ | |
{ | |
bornFlag = true; | |
} | |
px = lis.x; | |
py = lis.y; | |
pz = lis.z; | |
} | |
void setLed() | |
{ | |
RGB rgbMatrix[WIDTH][HEIGHT]; | |
// GRASS -------------------------------------- | |
for ( int y = 0; y < HEIGHT; y++) | |
{ | |
for ( int x = 0; x < WIDTH; x++) | |
{ | |
//rgbMatrixの初期化 | |
rgbMatrix[x][y].r = 0; | |
rgbMatrix[x][y].g = 0; | |
rgbMatrix[x][y].b = 0; | |
rgbMatrix[x][y].g += grassMatrix[x][y];//草の色を追加 | |
} | |
} | |
// ANIMAL -------------------------------------- | |
for ( int i = 0; i < ANIMAL_MAX_NUM; i++) | |
{ | |
if ( !animals[i].isDead ) | |
{ | |
//動物の色を追加 | |
rgbMatrix[int(animals[i].x)][int(animals[i].y)].r += animals[i].color.r; | |
rgbMatrix[int(animals[i].x)][int(animals[i].y)].g += animals[i].color.g; | |
rgbMatrix[int(animals[i].x)][int(animals[i].y)].b += animals[i].color.b; | |
} | |
} | |
// SET DATA ------------------------------------ | |
for ( int y = 0; y < HEIGHT; y++) | |
{ | |
for ( int x = 0; x < WIDTH; x++) | |
{ | |
//rgbMatrixの色をLEDににセットする | |
pixels.setPixelColor( ledMatrix[x][y], pixels.Color(rgbMatrix[x][y].r, rgbMatrix[x][y].g, rgbMatrix[x][y].b ) ); | |
} | |
} | |
pixels.show(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment