Форум программистов, компьютерный форум, киберфорум
Кроссплатфор­менная разработка
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.71/68: Рейтинг темы: голосов - 68, средняя оценка - 4.71
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562

Змейка

17.10.2010, 06:00. Показов 13647. Ответов 95
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
wxWidgets - вот и пошло первое написание игры. Ну относительно игры конечно. Проблема вот в чем. Нам препод показал как сделать, чтобы "змейка" двигалась. Поднастроил, чтобы она двигалась правильно. Влево - влево, вниз - вертикально вниз и т.п. Но есть проблемка. При таком коде, что соответственно:

C++
1
2
3
    m_coord +=
        wxGetKeyState(WXK_UP)? wxPoint(0, -10) : wxGetKeyState(WXK_DOWN) ? wxPoint(0, 10) : 
        wxGetKeyState(WXK_LEFT)? wxPoint(-10, 0) : wxGetKeyState(WXK_RIGHT)? wxPoint(10, 0) : wxPoint(10, 0);
Координата точки изменяется, только если держать кнопку. По дефолту идет вправо. Не коммильфо. Как запомнить последнюю нажатую кнопку и перемещать именно в ту сторону, какая кнопка была нажата?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.10.2010, 06:00
Ответы с готовыми решениями:

Змейка не работает
Неправильно работает хвост (add_hvost) . Что не так ? #include <iostream> #include <conio.h> #include <cstdlib> #include...

Змейка. Нужен совет как доработать программу
Недавно я зашел в тупик, работая над программой "Змейка". Но несмотря на то, что в общем и целом программа работает (змея двигается по...

Змейка на QT C++
Доброго времени суток! Начал изучение с++ QT и параллельно пробую писать игру змейка. Сама реализация игры почти готова - змейка...

95
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
26.10.2010, 22:08  [ТС]
Студворк — интернет-сервис помощи студентам
Попробовал устроить такое:

C++
1
2
3
4
5
6
7
8
9
10
    void DoMotion()
    {
        //for(size_t i=Sections.size()-2; i>-1; --i)
        //{
        //  std::swap(Sections[i].GetCoord(), Sections[i+1].GetCoord());
        //}
        Sections[Sections.size()-1].GetCoord()+=
            currSnakeDir==UP ? wxPoint(0, -10) : currSnakeDir==DOWN ? wxPoint(0, 10) :
            currSnakeDir==LEFT ? wxPoint(-10, 0) : currSnakeDir==RIGHT ? wxPoint(10, 0) : wxPoint(0, 0);
    }
Нам надо смещать последовательно элементы, т.е. при трех:
Последний меняется со вторым, первый меняется с теперешним вторым. В итоге последний на первом месте. Т.е. хвост на месте головы по сути. Хотя нет. Не на месте головы... Вообщем как лучше менять?
И потом голову мы перемещаем на нужные координаты. Так?

Добавлено через 4 минуты
ЗАРАБОТАЛО!!!

C++
1
2
3
4
5
6
7
8
9
10
11
    void DoMotion()
    {
        for(size_t i=Sections.size()-2; i>0; --i)
        {
            std::swap(Sections[i].GetCoord(), Sections[i+1].GetCoord());
        }
        Sections[1].SetCoord(Sections[0].GetCoord());
        Sections[0].GetCoord()+=
            currSnakeDir==UP ? wxPoint(0, -10) : currSnakeDir==DOWN ? wxPoint(0, 10) :
            currSnakeDir==LEFT ? wxPoint(-10, 0) : currSnakeDir==RIGHT ? wxPoint(10, 0) : wxPoint(0, 0);
    }
Добавлено через 3 часа 24 минуты
Итак. Оно работает. Полностью. Почти без нареканий.
Есть только 2 вопроса.
Как сделать, чтобы кол-во очков было видно постоянно и оно соответственно менялось? Пробовал пихнуть в статус-бар, но там оно остается 0 как и было изначально.
И второй вопрос: не обрабатывает врез змейки в саму себя при двух секциях. В чем может быть проблема?
Ну и последний: стоит-ли изменять код(статические переменные и некоторые другие вещи) и если да, то примерно как?

П.С. Код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//Food.h
#include "wx/wx.h"
 
class MyFood
{
public:
    MyFood(MyCanvas* Canv, const int rad_=10)
    {
        canv=Canv;
        rad=rad_;
    }
 
    ~MyFood()
    {
    }
 
    void SetCoord(const wxPoint& s)
    {
        food_coord.x=s.x;
        food_coord.y=s.y;
    }
 
    const wxPoint GetCoord() const
    {
        return food_coord;
    }
    
    void DrawFood(wxDC& dc)
    {
        dc.SetBrush(wxColour("Red"));
        dc.DrawCircle(GetCoord(), rad);
    }
private:
    wxPoint food_coord;
    MyCanvas* canv;
    int rad;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//Snake.h
#include <wx/wx.h>
 
#include <vector>
 
class MyCanvas;
 
enum Direction
{
    UP,
    RIGHT, 
    LEFT,
    DOWN,
    NONE
};
 
class MySection
{
public:
    MySection(const size_t radius=5, const wxPoint& point=wxPoint(0, 0)):
      sect_coord(point), 
          rad(radius)
    {
    }
 
    wxPoint& GetCoord()
    {
        return sect_coord;
    }
 
    void SetCoord(const wxPoint& c)
    {
        sect_coord.x=c.x;
        sect_coord.y=c.y;
    }
 
    void Draw (wxDC& dc)
    {
        dc.DrawCircle(sect_coord, rad);
    }
 
private:
    wxPoint sect_coord;
    size_t rad;
};
 
class MySnake
{
public:
    MySnake(MyCanvas* c, size_t sect_count=1)
    {
        canv=c;
        Sections.resize(sect_count);
    }
 
    bool DoMotion(const wxSize& size, const int one_c=10)
    {
        static size_t cnt=0;
        if(Sections.size()>1)
        {
            for(size_t i=Sections.size()-2; i>0; --i)
            {
                std::swap(Sections[i].GetCoord(), Sections[i+1].GetCoord());
            }
            Sections[1].SetCoord(Sections[0].GetCoord());
        }
        Sections[0].GetCoord()+=
            currSnakeDir==UP ? wxPoint(0, -one_c) : currSnakeDir==DOWN ? wxPoint(0, one_c) :
            currSnakeDir==LEFT ? wxPoint(-one_c, 0) : currSnakeDir==RIGHT ? wxPoint(one_c, 0) : wxPoint(0, 0);
        if(!isNotWall(size)||(cnt>=Sections.size()&&!isNotBroke()))
            return false;
        ++cnt;
        return true;
    }
    
    void Draw(wxDC& dc)
    {
        dc.SetBrush(wxColour("White"));
        for(size_t i=0; i<Sections.size(); ++i)
        {
            Sections[i].SetCoord(Sections[i].GetCoord());
            Sections[i].Draw(dc);
        }
    }
 
    void SetDir(const Direction& New)
    {
        currSnakeDir=New;
    }
 
    void add()
    {
        Sections.push_back(MySection(5, wxPoint(Sections[0].GetCoord())));
    }
 
    bool isNotWall(const wxSize& sz)
    {
        if(((Sections[0].GetCoord().x>=sz.x)||(Sections[0].GetCoord().y>=sz.y)) ||
            ((Sections[0].GetCoord().x<0)||(Sections[0].GetCoord().y<0)))
        {
            return false;
        }
        return true;
    }
 
    bool isNotBroke()
    {
        for(size_t j=1; j<Sections.size(); ++j)
        {
            if(Sections[0].GetCoord()==Sections[j].GetCoord())
            {
                return false;
            }
        }
        return true;
    }
 
    MySection& operator [](const size_t idx)
    {
        return Sections[idx];
    }
 
    const std::vector<MySection>& GetVec() const
    {
        return Sections;
    }
private:
    std::vector<MySection> Sections;
    MyCanvas* canv;
    Direction currSnakeDir;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//Minimal.cpp
class MyCanvas : public wxScrolledWindow
{
public:
    MyCanvas(MyFrame* POb):
      wxScrolledWindow(POb, wxID_ANY, wxDefaultPosition,
        wxSize(640, 480)),Sn(new MySnake(this)), Food(new MyFood(this)), points(0)
    {
        m_timer.SetOwner(this);
        m_timer.Start(500);
    }
    ~MyCanvas()
    {
       delete Sn;
       delete Food;
    }
 
    size_t points;
protected:
    void OnTimer(wxTimerEvent& event);
    void OnPaint(wxPaintEvent& event);
    void OnKeyboard(wxKeyEvent& event);
    void Invalidate()
    {
        Refresh();
    }
 
    wxTimer m_timer;
 
private:
    void DoDraw(wxDC& dc, const wxPoint& pt, const wxPoint& old_pt);
    void DoMotion(const Direction& curr);
    void DrawFood(wxDC& dc);
    bool CheckCoord();
    bool IsEaten(const size_t point=10);
 
    MySnake* Sn;
    MyFood* Food;
 
    DECLARE_EVENT_TABLE()
};
//
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxMessageBox(wxString::Format(
                    _T("Hello, this is Snake Game\n"
                 )),
                 _T("About Application"),
                 wxOK | wxICON_INFORMATION,
                 this);
}
 
void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc(this);
}
 
void MyCanvas::OnTimer(wxTimerEvent& WXUNUSED(event))
{
    wxSize CS = GetClientRect().GetSize();
    if(!Sn->DoMotion(CS))
    {
        m_timer.Stop();
        wxMessageBox(_T("Game over!\nYou lose!\n"), wxString::Format("You have %d points\n", points), wxOK | wxICON_ERROR, this);
        this->GetParent()->Close();
    }
    wxMemoryDC dc;
    dc.SelectObject(wxBitmap(CS.GetHeight(), CS.GetWidth()));
    Sn->Draw(dc);
    DrawFood(dc);
    wxClientDC clientDC(this);
    clientDC.Blit(wxPoint(0, 0), CS, &dc, wxPoint(0, 0));
}
 
void MyCanvas::OnKeyboard(wxKeyEvent& WXUNUSED(event))
{
    wxGetKeyState(WXK_UP) ? Sn->SetDir(UP) :
        wxGetKeyState(WXK_DOWN) ? Sn->SetDir(DOWN) :
        wxGetKeyState(WXK_RIGHT) ? Sn->SetDir(RIGHT) :
        wxGetKeyState(WXK_LEFT) ? Sn->SetDir(LEFT) :
        Sn->SetDir(NONE);
}
 
void MyCanvas::DrawFood(wxDC& dc)
{
    const int coord=10;
    static int cnt=0;
    const wxSize sz=GetClientRect().GetSize();
    if(cnt==0)
    {
        (*Food).SetCoord(wxPoint(coord*(rand()%(sz.x/coord)), coord*(rand()%(sz.y/coord))));
        while(!CheckCoord())
            (*Food).SetCoord(wxPoint(coord*(rand()%(sz.x/coord)), coord*(rand()%(sz.y/coord))));
    }
    if(IsEaten())
    {
        while(!CheckCoord())
            (*Food).SetCoord(wxPoint(coord*(rand()%(sz.x/coord)), coord*(rand()%(sz.y/coord))));
    }
    (*Food).DrawFood(dc);
    cnt++;
}
 
bool MyCanvas::CheckCoord()
{
    for(size_t i=0; i<Sn->GetVec().size(); ++i)
    {
        if(((*Sn)[i].GetCoord().x==(*Food).GetCoord().x)
            && ((*Sn)[i].GetCoord().y==(*Food).GetCoord().y))
            return false;
    }
    return true;
}
 
bool MyCanvas::IsEaten(const size_t point)
{
    if(((*Sn)[0].GetCoord().x==(*Food).GetCoord().x)
        && ((*Sn)[0].GetCoord().y==(*Food).GetCoord().y))
    {
        Sn->add();
        points+=point;
        return true;
    }
    return false;
}
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
27.10.2010, 02:03
Как сделать, чтобы кол-во очков было видно постоянно и оно соответственно менялось? Пробовал пихнуть в статус-бар, но там оно остается 0 как и было изначально.
Поставь слева или справа панель и на ней уже выводи всю необходимую информация. Чтобы понять как выравнивать элементы можешь скачать wxFormBuilder(GUI Designer) и поиграться с этим там.
И второй вопрос: не обрабатывает врез змейки в саму себя при двух секциях. В чем может быть проблема?
Сначала хвост становится на место головы(у тебя происходит обмен), а потом происходит шаг. Таким, образом голова всегда оказывается впереди хвоста и никогда в него не врезается. Вообще, насколько я помню в этой игре не бывает меньше трёх секций у змейки. Поэтому есть смысл проверять в конструкторе переданное значение, и если оно будет меньше трёх, то сбрасывать их количество на значение по-умолчанию(>=3).
Ну и последний: стоит-ли изменять код(статические переменные и некоторые другие вещи) и если да, то примерно как?
Да, использовать хотя бы deque вместо вектора. Не делать перестановок всей змейки(количество которых зависит от длины змейки), а переставлять только хвост(только одна перестановка, длина змейки не играет роли). Разбить код грамотно по файлам. Использовать Connect`ы вместо карт сообщений(но это естественно не обязательно))
C++
1
2
3
4
// в конструкторе
Connect( wxEVT_PAINT, wxPaintEventHandler(MyCanvas::OnPaint) );
Connect( wxEVT_KEY_DOWN, wxKeyEventHandler(MyCanvas::OnKeyboard) );
Connect( wxEVT_TIMER, wxTimerEventHandler(MyCanvas::OnTimer) );
Использовать switch вместо тернарного оператора. Использовать метод DrawFood(лучше переимновать просто в Draw) класса MyFood напрямую, а для генерации случайной позиции добавить в класс MyFood некий метод, который быдет этим заниматься(какой-нибудь setRandPosition). DrawFood из MyCanvas соответсвенно следует убрать. Для хранения очков, количества жизней и т.д. просто создай структуру(а может даже лучше класс) которая будет всё это хранить и сделай её членом класса канвы.
P.S. и паузу неплохо бы добавить )
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.10.2010, 02:27  [ТС]
rangerx,
Цитата Сообщение от rangerx Посмотреть сообщение
Поставь слева или справа панель и на ней уже выводи всю необходимую информация. Чтобы понять как выравнивать элементы можешь скачать wxFormBuilder(GUI Designer) и поиграться с этим там.
Только таким макаром возможно?


Цитата Сообщение от rangerx Посмотреть сообщение
Да, использовать хотя бы deque вместо вектора.
Не. Оставлю вектор) Препод долго удивлялся когда увидел дек.


Цитата Сообщение от rangerx Посмотреть сообщение
Не делать перестановок всей змейки(количество которых зависит от длины змейки), а переставлять только хвост(только одна перестановка, длина змейки не играет роли).
Как это возможно? Т.е. мы меняем значения только хвоста и головы? Но ведь тогда змейка "уплывет". Или только хвоста? Но тогда вроде как ничего хорошего не будет. Можешь принцип объяснить?


Цитата Сообщение от rangerx Посмотреть сообщение
Использовать метод DrawFood(лучше переимновать просто в Draw) класса MyFood напрямую, а для генерации случайной позиции добавить в класс MyFood некий метод, который быдет этим заниматься(какой-нибудь setRandPosition). DrawFood из MyCanvas соответсвенно следует убрать.
В этом проблема. Все же для того, чтобы рисовать еду, мне надо во первых убедится что она не попадает в координаты самой змейки, и потом проверять съедена-ли она + при выборе позици проверить не совпадает ли она.
То есть - мне нужно знать координаты и еды и вектора. Общность их проявляется только в Canvas-е, ибо до этого ни змейка ничего не знает о еде, ни еда о змейке. Как быть?


Цитата Сообщение от rangerx Посмотреть сообщение
Для хранения очков, количества жизней и т.д. просто создай структуру(а может даже лучше класс) которая будет всё это хранить и сделай её членом класса канвы.
Вариант. Но скорее всего пока будет только одна жизнь -> следовательно нужны только очки. Делать отдельный класс ради очков - мало смысла.


Цитата Сообщение от rangerx Посмотреть сообщение
P.S. и паузу неплохо бы добавить )
Можно поподробнее?
0
 Аватар для papochka
33 / 33 / 0
Регистрация: 14.11.2009
Сообщений: 137
27.10.2010, 13:34
А можно скомпилированный ехе? Уж очень интересно
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
27.10.2010, 14:38
Только таким макаром возможно?
Ну, я не знаю почему у тебя не получается со статусбаром. Да и использовать статусбар в играх как-то не сосвем правильно. Обычно в таких играх используют панель или что-то в этом роде, и уже туда выводят всё что нужно. Т.е. как-то так можно сделать. А с тем как работает выранивание виджетов проще всего разобраться используя wxFormBuilder(или какой-нибудь другой gui designer).
Не. Оставлю вектор) Препод долго удивлялся когда увидел дек.
Так может тебе лучше спросить у него, что именно он хочет увидеть. Дек лучше вектора для данной задачи, поэтому увидев вектор думаю он удивится не меньше. Возможно он хочет увидет вообще принципиально другое решение.
Как это возможно? Т.е. мы меняем значения только хвоста и головы? Но ведь тогда змейка "уплывет". Или только хвоста? Но тогда вроде как ничего хорошего не будет. Можешь принцип объяснить?
Я тебе уже несколько раз пытался объяснить, куда уж ещё? Я запускал вчера, то что ты выложил
C++
1
2
3
4
5
6
7
8
9
...
/*for(size_t i=Sections.size()-2; i>0; --i)
{
    std::swap(Sections[i].GetCoord(), Sections[i+1].GetCoord());
}
Sections[1].SetCoord(Sections[0].GetCoord());*/
Sections.insert( Sections.begin(), Sections.front() ); // !!!
Sections.pop_back();                                   // !!!
...
Никаких проблем, ничего никуда не плывёт. Это не совсем то, что о чём я говорю(с вектором это не сделать, тут нужно что-то вроде списка), но сам смысл тот же, т.е. с хвоста одно звено удаляется, а к голове наоборот добавляется. Хотя для вектора от этого алгоритма мало толку. Но лучше для начала оставь всё как есть и покажи преподу, может быть его устроит и такое решение. )
В этом проблема. Все же для того, чтобы рисовать еду, мне надо во первых убедится что она не попадает в координаты самой змейки, и потом проверять съедена-ли она + при выборе позици проверить не совпадает ли она.
То есть - мне нужно знать координаты и еды и вектора. Общность их проявляется только в Canvas-е, ибо до этого ни змейка ничего не знает о еде, ни еда о змейке. Как быть?
Опять же, насколько я помню еда в этой игре может появляется где угодно, в том числе и на змейке. Т.е. каждый реализует этот момент по-своему. Но если ты хочешь чтобы она не появлялась на змейке, то тут надо подумать(или оставить как есть))...
Можно поподробнее?
Допустим нажал пробел игра остановилась и в середине написано "PAUSE". Потом нажимаешь ещё раз и игра возабновляется. Т.е. обычная пазуа, как во всех играх.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.10.2010, 16:49  [ТС]
Ну, я не знаю почему у тебя не получается со статусбаром. Да и использовать статусбар в играх как-то не сосвем правильно. Обычно в таких играх используют панель или что-то в этом роде, и уже туда выводят всё что нужно. Т.е. как-то так можно сделать. А с тем как работает выранивание виджетов проще всего разобраться используя wxFormBuilder(или какой-нибудь другой gui designer).
Вот это надо будет посмотреть.


Так может тебе лучше спросить у него, что именно он хочет увидеть. Дек лучше вектора для данной задачи, поэтому увидев вектор думаю он удивится не меньше. Возможно он хочет увидет вообще принципиально другое решение.
Вектор. Но в сущности ему по барабану.

Никаких проблем, ничего никуда не плывёт. Это не совсем то, что о чём я говорю(с вектором это не сделать, тут нужно что-то вроде списка), но сам смысл тот же, т.е. с хвоста одно звено удаляется, а к голове наоборот добавляется. Хотя для вектора от этого алгоритма мало толку. Но лучше для начала оставь всё как есть и покажи преподу, может быть его устроит и такое решение. )
Как раз это ему и не понравилось. Он сказал что-то вроде:
"Как-то странно вы пытаетесь змейку двигать, то есть чтобы ей проползти вам надо оторвать ей хвост и приставить к голове (ну или что-то вроде), вообщем змейка-то и умереть так может".

Опять же, насколько я помню еда в этой игре может появляется где угодно, в том числе и на змейке. Т.е. каждый реализует этот момент по-своему. Но если ты хочешь чтобы она не появлялась на змейке, то тут надо подумать(или оставить как есть))...
Еда точно не должна появляться на змейке. Иначе это не коммильфо. Ни разу такого в змейке не видел.

Допустим нажал пробел игра остановилась и в середине написано "PAUSE". Потом нажимаешь ещё раз и игра возабновляется. Т.е. обычная пазуа, как во всех играх.
Интересная идея. Если по механике я так понимаю, что
ловим событие клавиатуры, если нажали пробел - то выдаем например бокс или еще какой диалог на тему паузы, и так же ставим таймер на стоп или паузу, если нажали пробел еще раз - запускаем таймер - игра продолжается, так?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
27.10.2010, 17:16
Как раз это ему и не понравилось. Он сказал что-то вроде:
"Как-то странно вы пытаетесь змейку двигать, то есть чтобы ей проползти вам надо оторвать ей хвост и приставить к голове (ну или что-то вроде), вообщем змейка-то и умереть так может".
Больше на шутку похоже, чем на то, что ему не понравился алгоритм Но лучше покажи ему, то что ты уже сделал, может ему подойдёт и так...
Интересная идея. Если по механике я так понимаю, что
ловим событие клавиатуры, если нажали пробел - то выдаем например бокс или еще какой диалог на тему паузы, и так же ставим таймер на стоп или паузу, если нажали пробел еще раз - запускаем таймер - игра продолжается, так?
Да, что-то вроде того.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.10.2010, 17:36  [ТС]
rangerx, Это и была шутка) Но сказал, что так нехорошо) Змейка должна быть живая xD
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 00:08  [ТС]
Сейчас ушел в шок...
Попробовал сделать релиз версию змейки, другу послать на тест...
Она начала выдавать мессаджбокс на тему проигрыша сходу... Вычислил, что дело в начальных координатах, передаю другие, работает, НО, змейка в дебаге начинающая расти вправо, здесь растет вверх оО.
Как такое может быть?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 00:21
А ты проинициализировал переменную currSnakeDir? Чему она у тебя равна в самом начале?
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 01:18  [ТС]
rangerx, Возможно в этом и есть дело. Надо бы. Ага. В этом было дело. ЗЫ
Вскрылся некоторый... Баг не баг... Даже не знаю. Вообщем когда мы открываем окно на полную, правая граница не ловит ошибки. Пробовал изменять размер клиентского окна в самой программе - не помогает. То есть за правую границу мы можем уйти сколько угодно далеко.
И еще... У меня при движение в противоположную сторону от движения змейки происходит конец игры... Но в основном в змейках - такое движение просто запрещено. Как реализовать? Что-то вроде prevSnakeDirr делать?

Добавлено через 33 минуты
Код для паузы. Или лучше использовать не мессаджбокс?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    case WXK_SPACE:
        {
            static int cnt=0;
            if(cnt%2==0)
            {
                m_timer.Stop();
                wxMessageBox(_T("Пауза!"), _T("\n"), wxOK, this);
            }
            else
            {
                m_timer.Start();
            }
            cnt++;
        }
        break;
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 01:22
Вообщем когда мы открываем окно на полную
А зачем тебе открывать его на полную? Сделай фиксированный размер окна. Т.е. стиль wxMINIMIZE_BOX | wxCLOSE_BOX | wxCAPTION для фрейма. А такой баг у меня не проявляется. Попробуй GetClientSize() использовать вместо GetClientRect().GetSize() в таймере.
У меня при движение в противоположную сторону от движения змейки происходит конец игры... Но в основном в змейках - такое движение просто запрещено. Как реализовать? Что-то вроде prevSnakeDirr делать?
В методе setDir сделай обработку какую-нибудь и всё.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 01:33  [ТС]
rangerx, GetClientSize() не помогло. Возвращает тоже самое, что и раньше было. А вот насчет неизменения это да. Надо.
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 01:38
Паузу я сам ради интереса вчера решил прикрутить, получилось так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// это вывод сообщения(какого угодно) на канве по середине окна
void MyCanvas::showMessage(const wxString& message)
{
    wxPaintDC dc(this);
    dc.SetFont( wxFont(16, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT) );
    dc.SetTextForeground(wxColour("White"));
    wxSize ts = dc.GetTextExtent(message);
    dc.DrawText(message, (GetClientSize().x - ts.x)/2, (GetClientSize().y - ts.y)/2);
}
 
// установка паузы
void MyCanvas::Pause()
{
    if(pause_) m_timer.Start();
    else m_timer.Stop();
    pause_ = !pause_;
}
pause_ закрытая переменная с самого начала инициализированная false.
При нажатии пробела
C++
1
2
3
4
        case WXK_SPACE:
            Pause();
            Refresh();
        break;
в OnPaint
C++
1
if(pause_) showMessage("PAUSE");
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 02:18  [ТС]
rangerx, Вах. Офигенно.

Не по теме:

Ты давно с виджетами работаешь?



Добавлено через 11 минут
Поставил фрейм так.

MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
wxMINIMIZE_BOX | wxCLOSE_BOX | wxCAPTION)

Действительно. Теперь не ресайзнуть. Но внизу таки есть ползунок нажимая на который мышью можно растянуть. Как сделать абсолютно фиксированный?

Добавлено через 25 минут
Интересно... Он постоянно оставляет канву на 414 394... Не могу понять почему.
Даже при таком в конструктор канвы, он все равно не растягивает как надо... Как поменять или закрыть изменение размера совсем?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 02:24
Действительно. Теперь не ресайзнуть. Но внизу таки есть ползунок нажимая на который мышью можно растянуть. Как сделать абсолютно фиксированный?
http://docs.wxwidgets.org/trunk/classwx_frame.html
Сразу после описания стилей.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 02:31  [ТС]
rangerx, о как. спасибо)
Но все же не могу понять, что делать с клиенстким окном... Оно остается одного и того же размера вне зависимости от размера фрейма (практически)

Добавлено через 2 минуты
На движение сделал так.

C++
1
2
3
4
5
6
7
8
9
10
    void SetDir(const Direction& New)
    {
        if((currSnakeDir==UP&&New==DOWN)||
            (currSnakeDir==DOWN&&New==UP)||
            (currSnakeDir==RIGHT&&New==LEFT)||
            (currSnakeDir==LEFT&&New==RIGHT))
            currSnakeDir=currSnakeDir;
        else
            currSnakeDir=New;
    }
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 02:41
Но все же не могу понять, что делать с клиенстким окном... Оно остается одного и того же размера вне зависимости от размера фрейма (практически)
Вообще оно должно растягиваться на весь фрейм, если не используешь сейзер... Пробуй использовать сейзер тогда, и на него уже ложи клиентское окно.
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2010, 19:18  [ТС]
rangerx, wxSizer?
Завтра почитаю про него и может что-нибудь получится. Спасибо тебе огромное. Без твоей помощи ничего бы вообще не вышло

Добавлено через 15 часов 48 минут
Ему вообще пофигу на то, что я посылаю... Как такое может быть? Он это ест... И рисует окно таким же размером какое и было... Как?...

C++
1
    MyCanvas* Ob= new MyCanvas(this, wxPoint(0, 0), wxSize(1, 1));
Добавлено через 44 минуты
Черт. Не въезжаю...

C++
1
2
3
4
5
6
7
8
    MyCanvas(MyFrame* POb):
      wxScrolledWindow(POb), Sn(new MySnake(this)), Food(new MyFood(this)), points(0), Sizer(new wxBoxSizer(0))
    {
        Sizer->Add(400, 400, 0, wxEXPAND);
        SetSizer(Sizer);
        m_timer.SetOwner(this);
        m_timer.Start(500);
    }
И ему пофиг... Как был размер клиентки так и остался... Я неправильно понял принцип использования?
0
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
29.10.2010, 19:27
А что ты хочешь чтобы у тебя получилось в конечном итоге?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.10.2010, 19:27

Ошибка undefined reference to в игре "Змейка"
В главном файле такие ошибки: #include &lt;QApplication&gt; #include &quot;Game.h&quot; Game* game; int main(int argc, char *argv) { ...

Прокомментировать код игры "змейка" в QT
Помогите прокомментировать код игры (подписать как, что и для чего).

Ошибки в игре "Змейка"
Не получается исправить ошибки в коде :(

Игра "Змейка": чтобы змейка не съедала сама себя
Здравствуйте! Пишу змейку на VB 2010. Не получается составить условие того, что бы змейка не ползла в направлении обратному...

Змейка
Написал только движение квадрата влево,вправо,вверх,вниз ,но не могу им управлять он движется до конца поля ,а только потом можно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru