DIY及创意
直播中

电子开发圈

5年用户 190经验值
擅长:DIY、Arduino、C51、STM32、FPGA
私信 关注

基于Arduino的“跑酷”游戏机设计步骤

1.jpg

游戏说明:

这是一个跑酷游戏, 需要火柴人(滑块)越过障碍(黑线), 若碰到黑线则游戏结束。


玩法:

1.上电启动,屏幕显示press key时按下按钮,屏幕会显示倒计时,倒计时时间为2s,因此在2s后就开始游戏了;

2. 当屏幕第一行显示”Go”第二行显示游戏时间时表示游戏正在进行中,你可以按下手中的按钮来让火柴人跳动,按一下火柴人跳动一下,按钮不支持长按,也就是说你一直按下按钮,火柴人也只是跳动一次;

3. 若在游戏过程中火柴人碰到了障碍物则游戏结束了,屏幕第一行显示“Game over”, 第二行显示你这次游戏的时间。

DIY:

1. 准备: L298电机驱动(也可以使用其他电机驱动)、红外对管黑线检测模块、LCD1602、key、舵机、直流减速电机、滚轮、传送带(纸)、框架、UNO;

2. 组装:

2.jpg

把各个模块与单片机连接就可以编写程序了

舵机的控制

舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:

0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;

红外对管黑线检测

3.jpg
4.jpg

当红外对管下面是黑色时由于黑色反光很弱,因此通过Q1的电流非常小,因此LM358的2脚的电压会接近电源电压,并且大于3脚的参考电压,此时LM358输出低电平,反之亦然。因此可以用单片机捕获这个电平变化。

参考程序

#include
#include
#include

#define BIT(x)(1<<(x))

Servomyservo;   
// create servoobject to control a servo
int key =4;       // key's pin
int motor =5;        // motor's pin
intsliding_block = 2;
int servo =9;            
int degree =100;         // servo degree
float game_time= 0;      // game's time
volatileunsigned int delay_counter = 0;  
// tomydelay()
booleangame_over = true;
boolean reset =true;     
LiquidCrystallcd(0);

void int0_init()       // get sliding_block's data
{
  DDRD &=~BIT(2);
  PORTD |= BIT(2);
  EICRA &=~BIT(1);
  EICRA |= BIT(0);
  EIFR |= BIT(0);       // clear flag
  EIMSK &=~BIT(0);         
}

voidtimer0_init()     // controlmotor
{  
  OCR0A = 100;
  OCR0B = 10;

  TCCR0A |= BIT(COM0A0) | BIT(COM0B1) | BIT(WGM01)| BIT(WGM00);     
  TCCR0B |= BIT(WGM02) | BIT(CS00);  
}

voidtimer2_init()               
// tomydelay(), because it seems like delay() can't be interrupted by otherinterrupt such as INT0
{
  TCCR2A = 0;
  TCCR2B = BIT(CS22) + BIT(CS21) +BIT(CS20);     // 1024 divide
  TCNT2 = 99;        //10ms
  TIMSK2 &= ~BIT(TOIE2);     
}

void lcd_init()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("   press key!  ");
  lcd.setBacklight(HIGH);
}

void setup()
{
  myservo.attach(servo);      
// attaches the servo on pin 9 to theservo object

  pinMode(motor, OUTPUT);
  timer0_init();     //motor

  pinMode(key, INPUT);
  pinMode(13, OUTPUT);    //LED
  digitalWrite(13, LOW);

  timer2_init();      //mydelay
  pinMode(sliding_block, INPUT);
  int0_init();       //sliding_block

  lcd_init();
  sei();
}

voidmydelay(unsigned int x, void (*fun)(void))     
//min=10ms
{
  unsigned int time_count = x/10;
  volatile unsigned int comp_count =delay_counter + time_count;
  //comp_count and delay_counter must is a volatilevariable

  TIMSK2 |= (1<   while(delay_counter < comp_count){                           
  //in order to notwaste CPU, you can execute your function in this loop
  if(0 != fun)
    fun();
  }
  TIMSK2 &=~(1< }

voidlcd_display(void)
{
  lcd.setCursor(6, 1);
  lcd.print(game_time);
}

void loop()
{
  static int key_time = 0;
  if(!game_over){
    if(!digitalRead(key)){
      if(key_time < 2)
        degree = 140;
      else
        degree = 100;
      key_time++;
    }
    else{
      degree = 100;
      key_time = 0;
    }     
    myservo.write(degree);                  
    // sets the servo positionaccording to the scaled value g
    if(degree > 120){
      mydelay(80, lcd_display);
      game_time += 0.1;
      mydelay(80, lcd_display);
      game_time += 0.1;
    }
    else{
      game_time += 0.1;
      mydelay(80, lcd_display);                           
     // waits for theservo to get there
    }   
  }else{   
    if(!reset){
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("   Game Over   ");
      lcd.setCursor(5, 1);
      lcd.print(game_time);
      mydelay(3000, 0);
    }
    reset = false;   
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("   press key!  ");

    while(digitalRead(key)){
      myservo.write(degree);                  
      // sets the servo positionaccording to the scaled value
      mydelay(32, 0);                           
      // waits for theservo to get there
      OCR0B = 10;
    }   
    mydelay(64, 0);
    while(!digitalRead(key));

    lcd.clear();
    lcd.setCursor(8, 0);
    lcd.print("2");
    mydelay(1000, 0);
    lcd.clear();
    lcd.setCursor(8, 0);   
    lcd.print("1");
    mydelay(1000, 0);
    lcd.clear();
    lcd.setCursor(7, 0);
    lcd.print("go");

    game_over = false;
    game_time = 0;
    OCR0B = 60;
    EIFR|= BIT(0);
    EIMSK |= BIT(0);         
    //enable extern interrupt 0
  }
}

ISR(INT0_vect)
{
  EIMSK &=~BIT(0);
  OCR0B = 10;
  game_over = true;
  TIMSK1 &=~BIT(TOIE1);
}

ISR(TIMER2_OVF_vect)
{
  TCNT2 = 99;       //10ms
  delay_counter++;
}






回帖(2)

王栋春

2018-12-9 22:13:42
学习一下
举报

xifu

2018-12-13 12:14:13
没看明白~~~~~~~~~~~~~~~~  筹字数
举报

更多回帖

发帖
×
20
完善资料,
赚取积分