自制贪吃蛇——碰撞检测,增加节点

  上篇地址 :http://www.cnblogs.com/chinxi/p/7190225.html

  接下来就是碰撞检测了,就是说,前面撞到东西了,或者是吃到东西了。

  之前在game.h里有个方法 Game::check_collision()是直接return 0的,现在直接修改这个方法。我的做法很简单,就是通过蛇头的坐标,和当前前进方向,获取下一个坐标,然后判断下个坐标的类型。

  为了复用获取下个坐标的方法,先是修改了Snake类:

 1  ///
 2  /// @file    snake.h
 3  /// @author  marrs(chenchengxi993@gmail.com)
 4  /// @date    2017-07-15 09:32:47
 5  ///
 6 
 7 #ifndef __SNAKE_H__
 8 #define __SNAKE_H__
 9 
10 #include "define.h" 
11 
12 namespace marrs{
13 
14 class Snake
15 {
16     public:
17         Snake();
18         ~Snake();
19 
20     public:
21         int init(char char_icon, int int_direction, int int_size, Coordinate coordinate);
22         int change_direction(int int_direction);    
23         int add_new_node(Coordinate coordinate_new, char char_icon_new);
24         int add_new_node(char char_icon_new);
25         Coordinate get_next_coordinate();    
26         Snake_Base* del_tail_node();
27         Snake_Base* forward();
28         Snake_Base* get_snake_base();
29         SnakeHead* get_snake_head();
30         int get_snake_size();
31 
32     private:
33         SnakeHead _snake;
34 
35 };
36 
37 }
38 
39 #endif

  增加了Coordinate get_next_coordinate()方法,并把原来 forward方法里获取下个坐标的方法直接换成调用新方法。这样,可以统一获取下个坐标的方式。

 1 Coordinate Snake::get_next_coordinate()
 2 {
 3     Coordinate coordinate = _snake.coordinate_cur;
 4 
 5     switch(_snake.int_direction)
 6     {
 7         case EN_DIR_UP:
 8             coordinate.int_x -= 1;
 9             break;
10         case EN_DIR_DOWN:    
11             coordinate.int_x += 1;
12             break;
13         case EN_DIR_LEFT:    
14             coordinate.int_y -= 1;
15             break;
16         case EN_DIR_RIGHT:    
17             coordinate.int_y += 1;
18             break;
19         default:break;
20 
21     }
22     return coordinate;
23 }
24 
25 Snake_Base* Snake::forward()
26 {
27     Snake_Base* pReturn = NULL;
28     if(_snake.int_size > 1)
29     {
30         add_new_node(_snake.coordinate_cur, _snake.char_icon);
31         pReturn = del_tail_node();
32     }
33     else
34     {
35         pReturn = new Snake_Base;
36         pReturn->coordinate_cur = _snake.coordinate_cur;
37     }
38     _snake.coordinate_cur = get_next_coordinate();
39     return pReturn;
40 
41 }

  然后是Game类里,的修改

int Game::check_collision()
{
    Coordinate coordinate = _snake.get_next_coordinate();
    MapBase map;
    int int_map_type = _map.get_map_val(coordinate.int_x, coordinate.int_y, map);
    switch(int_map_type)
    {
        case EN_MAP_WALL:
        case EN_MAP_SNAKE:
            return EN_COLLISION_DEAD;
        case EN_MAP_NEW_NODE:
            return EN_COLLISION_NEW_NODE;
        case EN_MAP_EMPTY:
        default:break;

    }

    return 0;
}

  由于目前并没有设置撞到东西之后会怎么处理,所以表现将会是撞到自己,或者墙之后,就停止不动了。

  现在要处理增加节点。

  首先,要能够随机在场景的某个坐标生成一个“食物”,并且不能与蛇、墙所在坐标重叠,即必须是个空地。

  

 1 int Game::gen_random_point()
 2 {
 3     if(_random_point.int_x * _random_point.int_y)
 4     {
 5         return 0;
 6     }
 7     MapBase map;
 8     while(true)
 9     {
10         while(_random_point.int_x == 0 || _random_point.int_x == _map.get_x_size() - 1)
11         {
12             _random_point.int_x = random(_map.get_x_size());
13         }
14         while(_random_point.int_y == 0 || _random_point.int_y == _map.get_y_size() - 1)
15         {
16             _random_point.int_y = random(_map.get_y_size());
17         }
18         int int_map_type = _map.get_map_val(_random_point.int_x, _random_point.int_y, map);
19         if (int_map_type == EN_MAP_EMPTY)
20         {
21             map.char_icon = '0';
22             map.int_type = EN_MAP_NEW_NODE;
23             _map.set_map_val(_random_point.int_x, _random_point.int_y, map);
24             break;
25         }else
26         {
27             reset_random_point();
28         }
29     }    
30 
31     return 0;
32 
33 }

  然后,我把它放在loop()中,forward之前地调用一次,如果需要,就生成一个随机坐标的食物。

  接着,就是碰撞检测出食物之后,增加节点。

 1 int Game::forward()
 2 {
 3     int int_ret = check_collision();
 4 
 5     switch(int_ret)
 6     {
 7         case EN_COLLISION_NEW_NODE:
 8             _snake.add_new_node(_snake.get_snake_head()->char_icon);
 9             reset_random_point();
10             break;
11         case EN_COLLISION_DEAD:
12             return EN_COLLISION_DEAD;
13         case EN_COLLISION_NEW_EMPTY:
14         default:break;
15 
16     }
17 
18     Snake_Base* snake_tmp = _snake.forward();
19 
20     _map.reset_point(snake_tmp->coordinate_cur.int_x, snake_tmp->coordinate_cur.int_y);
21     delete snake_tmp;
22     MapBase map_tmp;
23     map_tmp.int_type = EN_MAP_SNAKE;
24     map_tmp.char_icon = _snake.get_snake_head()->char_icon;
25     _map.set_map_val(_snake.get_snake_head()->coordinate_cur.int_x,
26                 _snake.get_snake_head()->coordinate_cur.int_y,
27                 map_tmp);
28 
29     return 0;
30 }

  此时,一个基本上能玩的贪吃蛇已经做好了。如果想让它撞墙就退出,或者触发一个函数,或者增加计分,甚至两条蛇一起玩,都是可以实现的。目前的这个程序,bug自然还是有的(囧)

  github:https://github.com/ccx19930930/Retro_Snaker

原文地址:https://www.cnblogs.com/chinxi/p/7191435.html