www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 工業(yè)控制 > 電路設(shè)計項目集錦
[導(dǎo)讀]這個代碼提供了一個簡單但引人入勝的坦克戰(zhàn)斗游戲體驗,結(jié)合了基本的移動,射擊和碰撞檢測機制。

這個代碼提供了一個簡單但引人入勝的坦克戰(zhàn)斗游戲體驗,結(jié)合了基本的移動,射擊和碰撞檢測機制。

這段代碼使用Arduino和Adafruit SSD1306庫在OLED顯示器上實現(xiàn)了一個基本的坦克戰(zhàn)斗游戲。以下是游戲的主要特點和功能:

?玩家坦克:玩家控制一輛坦克,它可以通過連接到特定引腳的按鈕向上、向下、向左和向右移動。坦克定時自動發(fā)射子彈。

?敵人坦克:有6輛敵人坦克在屏幕上隨機移動。每個敵方坦克也會向玩家的坦克發(fā)射子彈。

?子彈:玩家和敵人的坦克都會射擊子彈。子彈的速度是坦克移動速度的兩倍。當(dāng)玩家的子彈擊中敵人的坦克時,敵人的坦克就會被摧毀,玩家就會獲得一分。敵人的子彈不會影響其他敵人的坦克。

?碰撞檢測:游戲檢查玩家的子彈與敵人坦克之間的碰撞,以及敵人的子彈與玩家坦克之間的碰撞。如果敵人的子彈擊中玩家的坦克,玩家就會失去一條生命。

?生命和得分:玩家一開始有三條生命。每摧毀一輛敵方坦克,玩家的分?jǐn)?shù)就會增加。如果玩家失去所有三條生命,游戲?qū)@示“游戲結(jié)束”并重置。

?游戲重置:當(dāng)玩家的生命值為零時,游戲會顯示“游戲結(jié)束”屏幕,然后重新開始,重置分?jǐn)?shù)、玩家生命值和敵方坦克位置。

?顯示:游戲在OLED屏幕上顯示,游戲區(qū)和計分區(qū)用一條豎線隔開。得分區(qū)域顯示當(dāng)前得分和剩余命值。

?初始化和設(shè)置:在游戲開始時,敵人的坦克會出現(xiàn),玩家的坦克會出現(xiàn)在屏幕的中下方。游戲以一個顯示“Tank Battle”的啟動畫面開始。

圖表

坦克戰(zhàn)

這個代碼提供了一個簡單但引人入勝的坦克戰(zhàn)斗游戲體驗,結(jié)合了基本的移動,射擊和碰撞檢測機制。

代碼

#include

#include

#include

// Define constants

const int ENEMY_COUNT = 6;

const int SCREEN_WIDTH = 128;

const int SCREEN_HEIGHT = 64;

const int GAME_AREA_WIDTH = 100; // Game area width

const int SCORE_AREA_WIDTH = SCREEN_WIDTH - GAME_AREA_WIDTH; // Score area width

const int TANK_WIDTH = 6; // Tank width reduced by 5 times

const int TANK_HEIGHT = 6; // Tank height reduced by 5 times

const int BULLET_SPEED = 5; // Bullet speed

const int PLAYER_SHOT_INTERVAL = 1000; // Player tank firing interval in milliseconds

const int LIVES = 3; // Initial number of player tank lives

// Define I2C address and reset pin

#define OLED_RESET -1 // Use default reset pin

#define SCREEN_ADDRESS 0x3C

// Initialize OLED display

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Define direction enumeration

enum Direction { LEFT, RIGHT, UP, DOWN };

// Enemy structure

struct Enemy {

int x, y; // Position

int dx, dy; // Increment per frame

Direction dir; // Current moving direction

unsigned long lastShotTime; // Last firing time

bool active; // Whether the enemy is active

};

// Bullet structure

struct Bullet {

int x, y; // Position

int dx, dy; // Increment per frame

Direction dir; // Bullet direction

bool active; // Whether activated

};

// Global variables

Enemy enemies[ENEMY_COUNT];

Bullet bullets[10]; // Assume a maximum of 10 bullets at the same time

int playerX = GAME_AREA_WIDTH / 2 - TANK_WIDTH / 2; // Initial position of the player tank

int playerY = SCREEN_HEIGHT - TANK_HEIGHT - 1;

Direction playerDir = UP; // Initial direction of the player tank

unsigned long lastPlayerShotTime = 0; // Last firing time of the player tank

int score = 0; // Score

int lives = LIVES; // Player tank lives

void setup() {

// Initialize serial communication for debugging information

Serial.begin(9600);

// Initialize display

if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

Serial.println(F("SSD1306 allocation failed"));

for (;;); // If initialization fails, enter an infinite loop

}

display.clearDisplay();

// Show splash screen

showSplashScreen();

// Initialize enemies

for (int i = 0; i < ENEMY_COUNT; i++) {

spawnEnemy(i);

}

// Initialize bullets

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

bullets[i].active = false;

}

}

void loop() {

// Clear screen

display.clearDisplay();

// Detect button input to control player tank movement

if (digitalRead(2) == HIGH) { // Assume pin 2 is connected to the up direction key

playerDir = UP;

playerY = max(playerY - 1, 0);

} else if (digitalRead(3) == HIGH) { // Assume pin 3 is connected to the down direction key

playerDir = DOWN;

playerY = min(playerY + 1, SCREEN_HEIGHT - TANK_HEIGHT);

} else if (digitalRead(4) == HIGH) { // Assume pin 4 is connected to the left direction key

playerDir = LEFT;

playerX = max(playerX - 1, 0);

} else if (digitalRead(5) == HIGH) { // Assume pin 5 is connected to the right direction key

playerDir = RIGHT;

playerX = min(playerX + 1, GAME_AREA_WIDTH - TANK_WIDTH);

}

// Automatically fire player tank's bullets

if (millis() - lastPlayerShotTime > PLAYER_SHOT_INTERVAL) {

fireBullet(playerX + TANK_WIDTH / 2, playerY + TANK_HEIGHT / 2, playerDir);

lastPlayerShotTime = millis();

}

// Move enemies

moveEnemies();

// Automatically fire enemy bullets

autoFireEnemies();

// Update and draw bullets

updateBullets();

drawBullets();

// Check collisions

checkCollisions();

// Draw player tank

drawMiniTank(playerX, playerY, playerDir, 0);

// Draw enemies

drawEnemies();

// Draw vertical line to separate game area and score area

display.drawLine(GAME_AREA_WIDTH, 0, GAME_AREA_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);

// Show score

displayScore();

// Display content

display.display();

// If player tank's lives are used up, restart the game

if (lives <= 0) {

resetGame();

}

// Wait for a while to simulate frame rate

delay(50);

}

void showSplashScreen() {

// Set font size

display.setTextSize(2);

display.setTextColor(SSD1306_WHITE);

// Clear screen

display.clearDisplay();

// Calculate the width and height of "Tank" text

int16_t x1, y1;

uint16_t w1, h1;

display.getTextBounds("Tank", 0, 0, &x1, &y1, &w1, &h1);

// Calculate the width and height of "Battle" text

int16_t x2, y2;

uint16_t w2, h2;

display.getTextBounds("Battle", 0, 0, &x2, &y2, &w2, &h2);

// Calculate the total height of the two lines of text

uint16_t totalHeight = h1 + h2 + 4; // Add some spacing

// Calculate the starting y-coordinate to center the two lines of text

int16_t startY = (SCREEN_HEIGHT - totalHeight) / 2;

// Display "Tank" text, centered

display.setCursor((SCREEN_WIDTH - w1) / 2, startY);

display.println("Tank");

// Display "Battle" text, centered

display.setCursor((SCREEN_WIDTH - w2) / 2, startY + h1 + 4); // Add the height of the previous line and spacing

display.println("Battle");

// Update display

display.display();

// Pause for a while to allow the user to see the splash screen

delay(2000);

}

void drawMiniTank(int x, int y, Direction dir, int rotation) {

// Define the position and size of the tank's body and turret (reduced by 5 times)

int turretWidth = 2; // Turret width reduced by 5 times

int turretHeight = 2; // Turret height reduced by 5 times

// Calculate the turret's position based on the tank's moving direction

int turretX, turretY;

switch (dir) {

case LEFT:

turretX = x - turretWidth / 2;

turretY = y + (TANK_HEIGHT - turretHeight) / 2;

break;

case RIGHT:

turretX = x + TANK_WIDTH - turretWidth / 2;

turretY = y + (TANK_HEIGHT - turretHeight) / 2;

break;

case UP:

turretX = x + (TANK_WIDTH - turretWidth) / 2;

turretY = y - turretHeight;

break;

case DOWN:

turretX = x + (TANK_WIDTH - turretWidth) / 2;

turretY = y + TANK_HEIGHT - turretHeight / 2;

break;

}

// Draw the tank's body (square)

display.fillRect(x, y, TANK_WIDTH, TANK_HEIGHT, SSD1306_WHITE);

// Draw the tank's turret (small rectangle above the body)

display.fillRect(turretX, turretY, turretWidth, turretHeight, SSD1306_WHITE);

}

void moveEnemies() {

for (int i = 0; i < ENEMY_COUNT; i++) {

if (enemies[i].active) {

// Move the enemy

enemies[i].x += enemies[i].dx;

enemies[i].y += enemies[i].dy;

// If the enemy moves out of the screen, re-enter from the other side

if (enemies[i].x > GAME_AREA_WIDTH || enemies[i].x < 0) {

enemies[i].dx *= -1; // Reverse direction

enemies[i].dir = (enemies[i].dx > 0) ? RIGHT : LEFT;

}

if (enemies[i].y > SCREEN_HEIGHT || enemies[i].y < 0) {

enemies[i].dy *= -1; // Reverse direction

enemies[i].dir = (enemies[i].dy > 0) ? DOWN: UP;

}

}

}

}

void autoFireEnemies() {

for (int i = 0; i < ENEMY_COUNT; i++) {

if (enemies[i].active) {

if (millis() - enemies[i].lastShotTime > PLAYER_SHOT_INTERVAL) {

fireBullet(enemies[i].x + (TANK_WIDTH / 2) - 1, enemies[i].y + (TANK_HEIGHT / 2) - 1, enemies[i].dir);

enemies[i].lastShotTime = millis();

}

}

}

}

void fireBullet(int x, int y, Direction dir) {

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

if (!bullets[i].active) {

bullets[i].x = x;

bullets[i].y = y;

bullets[i].dir = dir;

bullets[i].active = true;

setBulletSpeed(bullets[i], dir);

break;

}

}

}

void setBulletSpeed(Bullet& bullet, Direction dir) {

switch (dir) {

case LEFT:

bullet.dx = -2 * BULLET_SPEED;

bullet.dy = 0;

break;

case RIGHT:

bullet.dx = 2 * BULLET_SPEED;

bullet.dy = 0;

break;

case UP:

bullet.dx = 0;

bullet.dy = -2 * BULLET_SPEED;

break;

case DOWN:

bullet.dx = 0;

bullet.dy = 2 * BULLET_SPEED;

break;

}

}

void drawEnemies() {

for (int i = 0; i < ENEMY_COUNT; i++) {

if (enemies[i].active) {

drawMiniTank(enemies[i].x, enemies[i].y, enemies[i].dir, 0);

}

}

}

void updateBullets() {

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

if (bullets[i].active) {

bullets[i].x += bullets[i].dx;

bullets[i].y += bullets[i].dy;

if (bullets[i].x < 0 || bullets[i].x > GAME_AREA_WIDTH || bullets[i].y < 0 || bullets[i].y > SCREEN_HEIGHT) {

bullets[i].active = false;

}

}

}

}

void drawBullets() {

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

if (bullets[i].active) {

display.fillRect(bullets[i].x, bullets[i].y, 2, 2, SSD1306_WHITE);

}

}

}

void checkCollisions() {

// Check for collisions between player bullets and enemies

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

if (bullets[i].active && bullets[i].dir == playerDir) { // Ensure it's the player's bullet

for (int j = 0; j < ENEMY_COUNT; j++) {

if (enemies[j].active && bullets[i].x >= enemies[j].x && bullets[i].x < enemies[j].x + TANK_WIDTH &&

bullets[i].y >= enemies[j].y && bullets[i].y < enemies[j].y + TANK_HEIGHT) {

// Player bullet hits enemy

bullets[i].active = false;

enemies[j].active = false;

score++; // Increase score

spawnEnemy(j); // Spawn a new enemy tank

break; // Exit inner loop

}

}

}

}

// Check for collisions between enemy bullets and player tank

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

if (bullets[i].active && bullets[i].dir != playerDir) { // Ensure it's the enemy's bullet

if (bullets[i].x >= playerX && bullets[i].x < playerX + TANK_WIDTH &&

bullets[i].y >= playerY && bullets[i].y < playerY + TANK_HEIGHT) {

// Enemy bullet hits player tank

bullets[i].active = false;

lives--; // Player tank loses a life

if (lives <= 0) {

resetGame(); // If lives are used up, restart the game

}

}

}

}

}

void spawnEnemy(int index) {

enemies[index].active = true;

if (index < ENEMY_COUNT / 2) {

enemies[index].x = random(0, GAME_AREA_WIDTH / 2);

enemies[index].y = random(0, SCREEN_HEIGHT);

enemies[index].dx = 1;

enemies[index].dy = 0;

enemies[index].dir = RIGHT;

} else {

enemies[index].x = random(0, GAME_AREA_WIDTH);

enemies[index].y = random(0, SCREEN_HEIGHT / 2);

enemies[index].dx = 0;

enemies[index].dy = 1;

enemies[index].dir = DOWN;

}

enemies[index].lastShotTime = millis() - PLAYER_SHOT_INTERVAL; // Ensure immediate firing

fireBullet(enemies[index].x + (TANK_WIDTH / 2) - 1, enemies[index].y + (TANK_HEIGHT / 2) - 1, enemies[index].dir);

}

void displayScore() {

display.setTextSize(1);

display.setTextColor(SSD1306_WHITE);

display.setCursor(GAME_AREA_WIDTH + 5, 0);

display.print("PTS");

display.setCursor(GAME_AREA_WIDTH + 10, 16);

display.println(score);

display.setCursor(GAME_AREA_WIDTH + 7, 32);

display.print("LV");

display.setCursor(GAME_AREA_WIDTH + 10, 48);

display.println(lives);

}

void resetGame() {

display.clearDisplay();

display.setTextSize(2);

display.setTextColor(SSD1306_WHITE);

int16_t x, y;

uint16_t w, h;

display.getTextBounds("Game Over", 0, 0, &x, &y, &w, &h);

display.setCursor((SCREEN_WIDTH - w) / 2, (SCREEN_HEIGHT - h) / 2);

display.println("Game Over");

display.display();

delay(3000);

for (int i = 0; i < ENEMY_COUNT; i++) {

spawnEnemy(i);

}

for (int i = 0; i < sizeof(bullets) / sizeof(bullets[0]); i++) {

bullets[i].active = false;

}

playerX = GAME_AREA_WIDTH / 2 - TANK_WIDTH / 2;

playerY = SCREEN_HEIGHT - TANK_HEIGHT - 1;

playerDir = UP;

score = 0;

lives = LIVES;

}

本文編譯自hackster.io

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

深圳2025年8月4日 /美通社/ -- 近日,電子元件和工業(yè)品數(shù)字化全球供應(yīng)商歐時RS聯(lián)合四方維(Supplyframe)創(chuàng)新中心成功舉辦 "歐時RS創(chuàng)客沙龍——Arduino主題開放日"?;顒泳劢归_源硬件與編程領(lǐng)軍平...

關(guān)鍵字: Arduino 開源 創(chuàng)客 智能未來

我們已經(jīng)看到了如何通過HC-05發(fā)送和接收數(shù)據(jù),但大多數(shù)藍(lán)牙應(yīng)用程序需要的不僅僅是發(fā)送和接收。在本教程中,我們將看到如何將HC-05與0.91英寸。OLED顯示屏打印HC-05接收到的數(shù)據(jù)。

關(guān)鍵字: OLED顯示器 Arduino HC-05藍(lán)牙模塊

ESP32模塊非常通用,可以通過WiFi連接到各種不同的平臺來發(fā)送和接收數(shù)據(jù)。在本教程中,我們將使用Arduino的物聯(lián)網(wǎng)云平臺(這是完全免費使用)與ESP32。有關(guān)Arduino IoT Cloud的更詳細(xì)概述,請查看...

關(guān)鍵字: GPS ESP32模塊 Arduino 物聯(lián)網(wǎng)

在這個中級電子和無線電通信教程中,我們將深入研究使用Arduino平臺和nRF24L01+無線模塊構(gòu)建功能齊全的8+通道RC(無線電控制)發(fā)射器和接收器。該項目結(jié)合了微控制器編程,傳感器集成和射頻通信的核心技能,非常適合...

關(guān)鍵字: Arduino RC控制器 發(fā)射器 接收器

作為飛行員,在空中和地面上,在飛行和飛行前的許多方面保持“安全第一”是很重要的,其中之一就是避免碰撞。過去幾年,即使是小型航空、自由飛行的飛機,如滑翔機、滑翔傘、懸掛式滑翔機等,在未來的無人機中,也開始采用儀器來觀察和讓...

關(guān)鍵字: Arduino ESP32 LED

用c++編程似乎是讓你的Arduino項目起步的障礙嗎?您想要一種更直觀的微控制器編程方式嗎?那你需要了解一下Visuino!這個圖形化編程平臺將復(fù)雜電子項目的創(chuàng)建變成了拖動和連接塊的簡單任務(wù)。在本文中,我們將帶您完成使...

關(guān)鍵字: Visuino Arduino ESP32 STM32

你有沒有想過Arduino是如何成為制造商和愛好者的強大工具的?在Arduino for Beginners課程的第二篇文章中,我們將探索Arduino背后的鼓舞人心的故事和一些展示其多功能性的實際應(yīng)用程序。最后,我將指...

關(guān)鍵字: LED Arduino UNO板

美國 賓夕法尼亞 MALVERN、中國 上海 — 2025年7月1日 — 日前,威世科技Vishay Intertechnology, Inc.(NYSE 股市代號:VSH)宣布,推出采用 0402外殼尺寸的新器件,擴展...

關(guān)鍵字: ADI Adafruit Arduino

本項目基于Wio Terminal(2.4寸液晶屏、物理按鍵、高效處理器)的硬件特性和Arduino開源生態(tài)系統(tǒng),實現(xiàn)了一款沉浸式F1賽車游戲。玩家通過按鍵控制賽車躲避障礙物,游戲難度隨分?jǐn)?shù)動態(tài)增加,結(jié)合專業(yè)的賽車圖形渲...

關(guān)鍵字: Arduino 開源生態(tài)系統(tǒng) Wio Terminal

使用LoRaWAN的智能水位和洪水警報系統(tǒng)。實時數(shù)據(jù)+環(huán)境。傳感器=零連接成本的早期預(yù)警。

關(guān)鍵字: Arduino LoRaWAN 傳感器
關(guān)閉