日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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

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

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

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

?敵人坦克:有6輛敵人坦克在屏幕上隨機(jī)移動(dòng)。每個(gè)敵方坦克也會(huì)向玩家的坦克發(fā)射子彈。

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

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

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

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

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

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

圖表

坦克戰(zhàn)

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

代碼

#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)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉