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


      上篇地址 :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

  • 相关阅读:
    基于u盘身份验证
    新的一年开始了~!
    asp.net的条形码
    windows phone (21) Grid元素的Background和Clip
    windows phone (19) 深入了解TextBlock
    windows phone (25) Canvas元素B
    windows phone (20) Image元素
    windows phone (22) 隐藏元素
    windows phone (26) ApplicationBar应用程序栏
    windows phone (27) 基础Button
  • 原文地址:https://www.cnblogs.com/chinxi/p/7191435.html
Copyright © 2020-2023  润新知