上篇地址 :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自然还是有的(囧)