小球游戏

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
    
#include <EEPROM.h>

#define OLED_RESET 4
#define SAVE_ADDR 0
Adafruit_SSD1306 oled(OLED_RESET);


#define block_r 16//弧形半径
#define enemy_amount 8
float block_length = 0.5*2*PI;//弧长
float block_deg = 0;//圆弧角度
//---------------------------------------
byte enemy_x[enemy_amount] = {};
byte enemy_y[enemy_amount] = {};//敌人坐标
float enemy_spd[enemy_amount] = {};//敌人速度
byte enemy_state[enemy_amount] = {};//敌人状态

uint32_t last_spawn = 0;
uint32_t start_time = 0;//游戏开始时间

byte life = 3;
unsigned int score = 0;
unsigned int highscore = 0;

void spawn_enemy(byte enemy_idx)//生成敌人--------------------------
{
    enemy_spd[enemy_idx] = 2;
    //在哪条边上生成
    byte place = random(4);
    if(place == 0)//left
    {
        enemy_x[enemy_idx] = 0;
        enemy_y[enemy_idx] = 0;//random(64);
    }
    else if(place == 1)//right
    {
        enemy_x[enemy_idx] = 127;
        enemy_y[enemy_idx] = random(64);
    }
    else if(place == 2)//up
    {
        enemy_x[enemy_idx] = random(128);
        enemy_y[enemy_idx] = 0;
    }
    else//down
    {
        enemy_x[enemy_idx] = random(128);
        enemy_y[enemy_idx] = 63;
    }
}

float get_angle(float x, float y)//获取角度--------------------------
{
    float ang = atan(y/x);
    if (x >= 0)
        return ang;
    else
        return ang + PI;
}

void centerDrawText(String text, byte cursor_y, byte f_size)
{
    oled.setTextSize(f_size);
    oled.setCursor(65 - text.length()*6*f_size/2, cursor_y);//*3 is *6pixel/2
    oled.print(text);
}

void control_block()//控制小弧形--------------------------
{
  //0~1023--->0~2*PI
  float deg = analogRead(A0)/512.0 *2*PI;
  if (deg >= 2*PI)
      deg -= (2*PI);
  block_deg = deg;
  for(float i = deg; i <= deg + block_length; i += 0.05)
  {
    byte x = 64 - cos(i) * block_r;
    byte y = 32 - sin(i) * block_r;
    oled.drawPixel(x, y, WHITE);//绘制像素
  }
}

void draw_time()//绘制时间--------------------------
{
    score = (millis() - start_time)/1000;
    centerDrawText(String(score), 30, 1);
}

void drawLife()//绘制生命--------------------------
{
    for(byte i = 0; i < life; i += 1)
    {
        oled.drawFastHLine(58 + i * 5, 25, 3, WHITE);
        oled.drawFastHLine(58 + i * 5, 26, 3, WHITE);
    }
}

void gameOver()//游戏结束--------------------------
{
    //最高分
    String t = "";
    if(score > highscore)
    {
        highscore = score;
        EEPROM.put(SAVE_ADDR, highscore);
        t = "NEW HIGHSCORE!";
    }
    else
    {
        t = "HIGHSCORE " + String(highscore);
    }
    //游戏结束转场
    oled.setTextColor(BLACK);
    for(byte i = 0; i <= 72; i += 6)
    {
        oled.fillCircle(64, 32, i, WHITE);
        centerDrawText("GAME OVER", 10, 1);
        centerDrawText(String(score), 25, 2);
        centerDrawText(t, 48, 1);
        oled.display();
    }
    delay(500);
    //等待输入重新开始
    int last_read = analogRead(A0);
    while(true)
    {
        int this_read = analogRead(A0);
        byte delta = abs(this_read - last_read);
        if(delta >= 10)
        {
            break;
        }
        last_read = this_read;
        delay(10);
    }
    //重新开始转场
    for(byte i = 0; i <= 72; i += 6)
    {
        oled.fillCircle(64, 32, i, BLACK);
        oled.display();
    }
    
    //参数重置
    life = 3;
    oled.setTextColor(WHITE);
    for(byte i = 0; i < enemy_amount; i += 1)
    {
        enemy_state[i] = 0;//删除所有敌人
    }
    start_time = millis();
}


void update_enemy(byte enemy_idx)//更新敌人--------------------------
{
    //更新坐标
    float xx = 64 - enemy_x[enemy_idx];
    float yy = 32 - enemy_y[enemy_idx];
    float deg = get_angle(xx, yy);
    
    float rr = sqrt(sq(xx) + sq(yy));
    float spdx = enemy_spd[enemy_idx] * cos(deg);
    float spdy = enemy_spd[enemy_idx] * sin(deg);
    enemy_x[enemy_idx] += spdx;
    enemy_y[enemy_idx] += spdy;
    //检查碰撞
    if(deg < 0)
      deg += 2 * PI;
    
    if(enemy_state[enemy_idx] == 1)//attack
    {
        if(rr <= block_r - 2)//in attack range---cant be block any more
            enemy_state[enemy_idx] = 2;
        else if(rr <= block_r + 2)//can be block
        {
            if(block_deg + block_length < 2 * PI)
            {
                if(deg >= block_deg and deg <= block_deg + block_length)
                    enemy_state[enemy_idx] = 0;
            }
            else
            {
                if(deg >= block_deg or deg <= block_deg + block_length - 2* PI)
                  enemy_state[enemy_idx] = 0;
            }
        }
    }
    else if(enemy_state[enemy_idx] == 2)//attack fin
    {
      if(rr <= 3)
            {
                enemy_state[enemy_idx] = 0;
                life -= 1;
                if (life == 0)
                    gameOver();//game over
            }
    }
}
///
void setup() {
    oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    oled.clearDisplay();
    oled.display();
  
    oled.setTextSize(1);
    oled.setTextColor(WHITE);
    

    pinMode(A0, INPUT);//定义电位器为输入
    Serial.begin(9600);
    randomSeed(analogRead(A1));
    for(int i = 0; i < enemy_amount; i += 1)
    {
        enemy_state[i] = 0;
    }
    //最高分
    EEPROM.get(SAVE_ADDR, highscore);
    Serial.print(highscore);
}

void loop() {
  oled.clearDisplay();
  draw_time();
  drawLife();
  control_block();
  uint32_t this_time = millis();
  
  if (this_time - last_spawn >= 1000)
  {
      last_spawn = this_time;
      for(int i = 0; i < enemy_amount; i += 1)
      {
          if(enemy_state[i] == 0)
          {
              spawn_enemy(i);
              enemy_state[i] = 1;
              break;
          }
      }
  }
  
  for(int i = 0; i < enemy_amount; i += 1)
  {
      if(enemy_state[i] != 0)
      {
          update_enemy(i);
          oled.drawCircle(enemy_x[i], enemy_y[i], 2, WHITE);
      }
  }
  oled.display();
}

转载于:https://my.oschina.net/u/4170695/blog/3083832

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值