Hardware components | ||||||
![]() |
| × | 1 |
The line represents the center of the road.
The car you’ll drive in the game appears on screen.
✨ Smoke was even added to the car’s muffler for extra realism!
🎮 <スタート画面>線は道路のセンターラインになっています。ゲームで実際に運転する車が画面に表示されます。
✨ 車のマフラーから出る煙も作成して、リアルさを演出しました!
Control the car using the first button from left and first button from right on the M5Stack.
- Yellow circles are coins → plus 5 points
- Gray objects are trash cans → collision causes vibration and reduces “life” and deducts 2 points
🔴 Red dots represent life
<ゲームスタート!>車の操作は M5Stack の左ボタンと右ボタンで左右に動かします。
- 黄色い丸はコイン → 5点加点されます
- グレーの物体はゴミ箱 → ぶつかると振動して命が減り、2点減点されます
- 🔴 赤い点は「命」を表します
Three red dots displayed at the bottom of the screen represent your lives.
Each time you hit a trash can, you lose 2 points and one red life dot fades away.
❤️<命のシステム>
画面下には、スコアと三つの赤い点が表示されており、それらが命を示しています。ゴミ箱にぶつかるたびに、2点減点され、命の赤い点がひとつずつ消えていきます。
Light green objects are cactus.
Colliding with a cactus results it doesn't affect your lives but, deducts 5 from your score.
🌵<サボテン>黄緑色の物体はサボテンです。サボテンにぶつかると減点されますが、命は減りません。
Sometimes the original car size makes it hard to avoid obstacles like trash cans or cactus.
Pressing the middle button on the M5 allows you to shrink the car size for more agile movements.
📉<サイズダウン!>車が元のサイズでは、ゴミ箱やサボテンをうまく避けられない場面があります。そんなときは、M5の真ん中のボタンを押すことで、車をサイズダウンしてよりすばやく動かせるようになります。
When all lives are lost, it's Game Over.
To restart, simply tap the screen to return to the starting state.
✖ <ゲームオーバー>命がすべてなくなると、ゲームオーバーになります。もう一度プレイするには、画面をタッチするとスタート画面に戻ります。
~Thank you<3~I made this for a school project. We have a subject that teaches us about the Internet of Things, and M5Stack is one of the hardware components we use. It works with simple programming, so it was fun to work with. I created this because I hope this kind of IoT technology can get into the small cute hands of children, so they can see how programming affects hardware.
これは学校のプロジェクトで作ったものです。授業でIoT(モノのインターネット)について学んでいて、M5Stackというハードウェアを使いました。簡単なプログラミングで動かせるので、楽しく作業できました。この作品を作ったのは、このようなIoT機器が子どもたちの小さな手に渡って、プログラミングでモノが動くっていう面白さを感じてもらえたらいいなと思ったからです。
#include <M5Core2.h>
//-----------------------------------------------------
//
//-----------------------------------------------------
void setup(void);
void loop(void);
void dispReady(void);
void dispGameover(void);
void gameInit(void);
void mydrawCar(void); //paddle
void moveCar(void);
void myscore(void);
void mydrawLine(int offsetY);
void moveTrash(void);
void drawTrashBox(void);
void moveCactus(void);
void drawCactus(void);
void drawMedal(void);
void moveMedal(void);
void carsmall(void);
void drawSideCar(void);
void drawSmokeDots(void);
//-----------------------------------------------------
//
//-----------------------------------------------------
TFT_eSprite sprite = TFT_eSprite(&M5.Lcd);
int carDirection = 1; // 1 = moving right, -1 = moving left
int carSpeed = 4; // speed of car movement 3
//
int trashX = 70;
int trashY = -60;
//
int cactusY = 0 ;
int cactusX = -100;
//
int medalX;
int medalY;
int prevMedalX = -999;
//
int prevTrashX = -999;
//
float x = 0; //170
float y = 130;
//
int score = 0; //
//-----------------------------------------------------
//
//-----------------------------------------------------
int gameStatus = 0; //
bool isSmallCar = false;
int lives = 3; // 3
int carX = 100; // X, Y
int carY = 50;
//
int baseX = 110;
int baseY = 230;
//-----------------------------------------------------
//setup
//-----------------------------------------------------
void setup() {
M5.begin();
//
Serial.begin(115200);
sprite.createSprite(M5.Lcd.width(), M5.Lcd.height());
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void loop() {
// TouchPoint_t pos; //
M5.update();
TouchPoint_t pos = M5.Touch.getPressPoint();
int carWidth = isSmallCar ? 40 : 80; //
int carHeight = isSmallCar ? 15 : 30;
//
if (gameStatus == 1) { // Game running
if(M5.BtnA.isPressed() == 1 ){
x -= carSpeed;// Move car left
if (x < 0) x = 0;
}
if (M5.BtnB.isPressed() == 1 ) {
isSmallCar = !isSmallCar; // truefalse
delay(30); //
}
if (M5.BtnC.isPressed() == 1 ) {
x += carSpeed;
int carWidth = isSmallCar ? 40 : 80;
if (x > M5.Lcd.width() - carWidth) x = M5.Lcd.width() - carWidth; //
}
}
//
if(gameStatus != 1){
//
switch (gameStatus){
case 0:
dispReady();
break; //----BRK
case 2:
dispGameover();
break; //----BRK
}
//
pos = M5.Touch.getPressPoint();
if(pos.x != -1){
//
gameInit();
//
gameStatus = 1;
}
}else{
static int offsetY = 0; //
offsetY += 10; //5
if (offsetY >= 240) offsetY = 0; // Wrap around screen height
//
pos = M5.Touch.getPressPoint();
if (pos.x != -1) {
if (pos.x < M5.Lcd.width() / 2) {
x -= carSpeed;
if (x < 0) x = 0;
} else {
x += carSpeed;
int carWidth = isSmallCar ? 40 : 80;
if (x > M5.Lcd.width() - carWidth) x = M5.Lcd.width() - carWidth;
}
}
//
sprite.fillScreen(WHITE);
mydrawLine(offsetY);
int carWidth;
if (isSmallCar) {
carWidth = 40;
} else {
carWidth = 80;
}
int carHeight;
if (isSmallCar) {
carHeight = 15;
} else {
carHeight = 30;
}
//
if (x + carWidth > trashX && x < trashX + 70 && y + carHeight > trashY && y < trashY + 60) {
score -= 2; //
trashY = -60; //
lives--; // 1
// //
// M5.Axp.SetLDOEnable(3, true);
// delay(50);
// M5.Axp.SetLDOEnable(3, false);
if (lives <= 0) {
gameStatus = 2; //
}
}
if (x + carWidth > medalX && x < medalX + 60 && y + carHeight > medalY && y < medalY + 80) {
score += 5;
medalY = -80;
}
if (x + 80 > medalX && x < medalX + 60 && y + 30 > medalY && y < medalY + 80) {
score += 5;
medalY = -80;
}
int cactusWidth = 40 * 0.8; //
int cactusHeight = 80 * 0.8; // + +
if (x + carWidth > cactusX && x < cactusX + cactusWidth &&
y + carHeight > cactusY && y < cactusY + cactusHeight) {
score -= 5; // 5
cactusY = -80; //
cactusX = random(0, M5.Lcd.width() - cactusWidth);
}
moveTrash();
moveCactus();
drawMedal();
moveMedal();
drawTrashBox();
drawCactus();
mydrawCar();
myscore();
//sprite
sprite.pushSprite(0, 0);
}
delay(50); //
}
//-----------------------------------------------------
//Ready
//-----------------------------------------------------
void dispReady() {
int centerX;
// "TOUCH"
sprite.fillScreen(WHITE);
sprite.setTextSize(3);
centerX = (320 - 3 * 6 * 5) / 2;// 5 6px 3
sprite.setCursor(centerX, 88);
sprite.setTextColor(BLUE);
sprite.println("TOUCH");
// "to"
centerX = (320 - 3 * 6 * 2) / 2;
sprite.setCursor(centerX, 120);
sprite.setTextColor(BLACK);
sprite.println("to");
// "START"
centerX = (320 - 3 * 6 * 5) / 2;
sprite.setCursor(centerX, 152);
sprite.setTextColor(RED);
sprite.println("START");
//
sprite.setCursor(10, 212);
sprite.setTextColor(BLACK);
sprite.println("- - - - - -");
//
carX = (320 - 80) / 2; // 80px
carY = 180; //
drawSideCar();
drawSmokeDots();
sprite.pushSprite(0, 0);
}
//-----------------------------------------------------
//Gameover
//-----------------------------------------------------
void dispGameover() {
sprite.fillScreen(BLACK); //
sprite.setTextSize(3); //
sprite.setTextColor(RED); //
sprite.setCursor(60, 80);
sprite.println(" GAME OVER");
sprite.setCursor(40, 130);
sprite.setTextColor(WHITE);
sprite.setTextSize(2);
sprite.print(" Final Score: ");
sprite.println(score);
sprite.setCursor(30, 180);
sprite.setTextColor(WHITE);
sprite.setTextSize(2);
sprite.println(" TOUCH TO RESTART");
sprite.pushSprite(0, 0); //
delay(300);
}
//-----------------------------------------------------
//
//----------------------------------------------------
void gameInit(){
x = (M5.Lcd.width() - 80) / 2; //
y = 130;
carDirection = 0;
trashX = 70;
trashY = -60;
medalX = 20;
medalY = -80;
score = 0; //
lives = 3;
prevTrashX = 0;
prevMedalX = 0;
isSmallCar = false;
}
//-----------------------------------------------------
//
//----------------------------------------------------
void mydrawLine(int offsetY){
int y1 = (0 + offsetY) % 240; //0
int y2 = (120 + offsetY) % 240;//120
sprite.drawRect(155, y1, 10, 50, BLACK); //X Y W H 320 240
sprite.fillRect(155, y1, 10, 50, BLACK);
sprite.drawRect(155, y2, 10, 50, BLACK);
sprite.fillRect(155, y2, 10, 50, BLACK);//
}
//-----------------------------------------------------
//CAR
//-----------------------------------------------------
void mydrawCar() {
// if (isSmallCar) {
// carsmall(); //
// return;
// }
if (isSmallCar) {
carsmall(); //
} else {
//
sprite.fillRect(x + 10 , y - 20, 60, 20, BLACK);
sprite.fillRect(x, y, 80, 30, BLUE);
//
sprite.fillRect(x + 2, y + 2, 15, 15, RED);
sprite.fillRect(x + 62, y + 2, 15, 15, RED);
//
sprite.fillRect(x + 1, y + 30, 20, 20, BLACK);
sprite.fillRect(x + 59, y + 30, 20, 20, BLACK);
}
}
//-----------------------------------------------------
//carsmall
//-----------------------------------------------------
void carsmall() {
float scale = 0.5; //
//
sprite.fillRect(x + 10 * scale , y - 20 * scale, 60 * scale, 20 * scale, BLACK);
//
sprite.fillRect(x, y, 80 * scale, 30 * scale, BLUE);
//
sprite.fillRect(x + 2 * scale, y + 2 * scale, 15 * scale, 15 * scale, RED);
sprite.fillRect(x + 62 * scale, y + 2 * scale, 15 * scale, 15 * scale, RED);
//
sprite.fillRect(x + 1 * scale, y + 30 * scale, 20 * scale, 20 * scale, BLACK);
sprite.fillRect(x + 59 * scale, y + 30 * scale, 20 * scale, 20 * scale, BLACK);
}
//-----------------------------------------------------
//SCORE
//-----------------------------------------------------
void myscore() {
sprite.setCursor(10, 210); // x=10, y=210
sprite.setTextColor(BLACK); //
sprite.setTextSize(3); //
sprite.print("SCORE"); //
sprite.print(score); //
//
int heartX = 200;
int heartY = 210;
for (int i = 0; i < 3; i++) {
if (i < lives) {
sprite.fillCircle(heartX + i * 20, heartY + 10, 8, RED);
} else {
sprite.drawCircle(heartX + i * 20, heartY + 10, 8, RED);
}
}
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void moveCar(){
x = (M5.Lcd.width() - 10) / 2;
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void drawTrashBox() {
float scale = 0.8;
//
sprite.drawRect(trashX + scale * 30, trashY + scale * 0 , scale * 10, scale * 4, BLACK);
sprite.fillRect(trashX + scale * 30, trashY + scale * 0 , scale * 10, scale * 4, DARKGREY);
//
sprite.drawRect(trashX + scale * 0, trashY + scale * 4 , scale * 70, scale * 10, BLACK);
sprite.fillRect(trashX + scale * 0, trashY + scale * 4 , scale * 70, scale * 10, DARKGREY);
//
sprite.drawRect(trashX + scale * 6, trashY + scale * 14, scale * 50, scale * 40, BLACK);
sprite.fillRect(trashX + scale * 6, trashY + scale * 14, scale * 50, scale * 40, LIGHTGREY);
//
sprite.drawRect(trashX + scale * 7, trashY + scale * 14, scale * 10, scale * 40, BLACK);
sprite.fillRect(trashX + scale * 7, trashY + scale * 14, scale * 10, scale * 40, DARKGREY);
sprite.drawRect(trashX + scale * 30, trashY + scale * 14, scale * 10, scale * 40, BLACK);
sprite.fillRect(trashX + scale * 30, trashY + scale * 14, scale * 10, scale * 40, DARKGREY);
sprite.drawRect(trashX + scale * 54, trashY + scale * 14, scale * 10, scale * 40, BLACK);
sprite.fillRect(trashX + scale * 54, trashY + scale * 14, scale * 10, scale * 40, DARKGREY);
//
sprite.drawRect(trashX + scale * 10, trashY + scale * 54, scale * 50, scale * 10, BLACK);
sprite.fillRect(trashX + scale * 10, trashY + scale * 54, scale * 50, scale * 10, DARKGREY);
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void moveTrash() {
trashY += 5;
if (trashY > M5.Lcd.height()) {
trashY = -60;
for (int i = 0; i < 10; i++) {
int newX = random(0, M5.Lcd.width() - 70);//70px
if (abs(newX - medalX) > 60 && abs(newX - prevTrashX) > 30) { //70 30 (medal trash ) 30px
prevTrashX = trashX; //
trashX = newX;
break;
}
}
}
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void drawCactus() {
float scale = 0.8;
//
sprite.drawRect(cactusX + scale * 20, cactusY + scale * 20, scale * 20, scale * 50, BLACK);
sprite.fillRect(cactusX + scale * 20, cactusY + scale * 20, scale * 20, scale * 50, GREEN);
//
sprite.drawRect(cactusX + scale * 5, cactusY + scale * 30, scale * 10, scale * 20, BLACK);
sprite.fillRect(cactusX + scale * 5, cactusY + scale * 30, scale * 10, scale * 20, GREEN);
sprite.drawRect(cactusX + scale * 5, cactusY + scale * 30, scale * 10, scale * 5, BLACK); //
sprite.fillRect(cactusX + scale * 5, cactusY + scale * 30, scale * 10, scale * 5, GREEN);
//
sprite.drawRect(cactusX + scale * 45, cactusY + scale * 30, scale * 10, scale * 20, BLACK);
sprite.fillRect(cactusX + scale * 45, cactusY + scale * 30, scale * 10, scale * 20, GREEN);
sprite.drawRect(cactusX + scale * 45, cactusY + scale * 30, scale * 10, scale * 5, BLACK);
sprite.fillRect(cactusX + scale * 45, cactusY + scale * 30, scale * 10, scale * 5, GREEN);
//
sprite.drawRect(cactusX + scale * 15, cactusY + scale * 70, scale * 30, scale * 10, BLACK);
sprite.fillRect(cactusX + scale * 15, cactusY + scale * 70, scale * 30, scale * 10, BLACK);
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void moveCactus() {
cactusY += 5; //
if (cactusY > M5.Lcd.height()) {
cactusY = -80; //
cactusX = random(0, M5.Lcd.width() - 60);
}
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void moveMedal() {
medalY += 5;
if (medalY > M5.Lcd.height()) {
medalY = -80;
for (int i = 0; i < 10; i++) {
int newX = random(0, M5.Lcd.width() - 60); //
if (abs(newX - trashX) > 70 && abs(newX - prevMedalX) > 30) {
prevMedalX = medalX;
medalX = newX;
break;
}
}
}
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void drawMedal() {
float scale = 0.8;
int centerX = medalX + scale * 40; // X80
int centerY = medalY + scale * 40; // Y80
int radius = scale * 30; //
// -
sprite.fillCircle(centerX, centerY, radius, TFT_ORANGE);
// -
sprite.fillCircle(centerX, centerY, radius - 2, YELLOW);
//
sprite.setTextSize(3);
sprite.setTextColor(BLACK);
sprite.setCursor(centerX - 6, centerY - 8);
sprite.print("$"); //
}
//-----------------------------------------------------
//
//-----------------------------------------------------
void drawSideCar() {
float scale = 0.8;
int bodyX = carX;
int bodyY = carY;
//
sprite.fillRect(bodyX + scale * 10, bodyY + scale * 30, scale * 65, scale * 20, BLUE); //
sprite.fillRect(bodyX + scale * 20, bodyY + scale * 20, scale * 40, scale * 15, BLUE); //
//
sprite.fillRect(bodyX + scale * 25, bodyY + scale * 22, scale * 12, scale * 10, LIGHTGREY);
sprite.fillRect(bodyX + scale * 45, bodyY + scale * 22, scale * 12, scale * 10, LIGHTGREY);
//
sprite.fillRect(bodyX + scale * 10, bodyY + scale * 32, scale * 5, scale * 5, RED);//15 35 5 5
//
sprite.fillRect(bodyX + scale * 68, bodyY + scale * 32, scale * 7, scale * 5, YELLOW);//
//
int wheelY = bodyY + scale * 47;
sprite.fillCircle(bodyX + scale * 20, wheelY, scale * 7, BLACK);
sprite.fillCircle(bodyX + scale * 65, wheelY, scale * 7, BLACK);
//
sprite.fillCircle(bodyX + scale * 20, wheelY, scale * 3, DARKGREY);
sprite.fillCircle(bodyX + scale * 65, wheelY, scale * 3, DARKGREY);
}
void drawSmokeDots() {
// 3
float scale = 0.8;
//
sprite.fillCircle(baseX, baseY, scale * 6, LIGHTGREY);
//
sprite.fillCircle(baseX + scale * 8, baseY - scale * 4, scale * 4, LIGHTGREY);
//
sprite.fillCircle(baseX + scale * 14, baseY - scale * 8, scale * 2, LIGHTGREY);
}
Comments