Делаю консольную игру, гонки из тетриса) Сделал движение, символ двигается по карте, но заходит за рамки, что то наделал что теперь если заезжает за правую сторону карты, выезжает с слевой, а если к левой едит, то просто прижимается.
#include <iostream>
#include <string.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
using namespace std;
enum Direction
{
STOP = 0, LEFT = 1, RIGHT = 2, UP = 3, DOWN = 4 //Движение
};
struct BadCar
{
struct {
int x;
int y; // Машина которая двигается вниз автоматом (ЕЩЕ НЕ СДЕЛАНО)
}head;
};
struct Cars
{
struct {
int x;
int y;
}head;
Direction dir;
};
struct Filed
{
const int width = 20;
const int height = 20;
};
void StartGame(Filed &filed, Cars &car)
{
car.dir = STOP;
car.head.x = filed.width / 2;
car.head.y = filed.height / 2;
}
void BadCarGame(Filed &filed, BadCar BadCar)
{
BadCar.head.x = filed.width / 2;
BadCar.head.y = filed.height / 2;
}
void IzField(Filed &filed, Cars &car)
{
car.head.x = STOP;
}
void PrintFiled(Filed filed, Cars car,BadCar BadCar)
{
system("cls");
cout « (char)218;
for (int i = 1; i < filed.width + 1; i++)
{
cout « (char)196;
}
cout « (char)191 « "\n";
for (int i = 0; i < filed.height + 2; i++)
{
for (int j = 0; j < filed.width + 2; j++)
{
if (j == 0)
{
cout « (char)179;
}
if (car.head.x == j && car.head.y == i)
{
cout « '*';
}
if (BadCar.head.x == j && BadCar.head.y == i)
{
cout « "=";
}
else
{
bool IsPrintTail = false;
if (!IsPrintTail)
{
cout « " ";
}
}
if (j == filed.width - 1)
{
cout « (char)179;
}
}
cout « "\n";
}
cout « (char)192;
for (int i = 1; i < filed.width + 1; i++)
{
cout « (char)196;
}
cout « (char)217;
cout « "\n";
}
void KeyPressEvent(Cars &car)
{
if (_kbhit())
{
switch (_getch())
{
case 75:
car.dir = LEFT;
break;
case 77:
car.dir = RIGHT;
break;
case 80:
car.dir = DOWN;
break;
case 72:
car.dir = UP;
break;
case 27:
exit(0);
}
}
}
void move(Filed &filed, Cars &car)
{
switch (car.dir)
{
case LEFT: car.head.x--;
break;
case RIGHT: car.head.x++;
break;
case UP: car.head.y--;
break;
case DOWN: car.head.y++;
break;
}
}
bool IsField(Filed &filed, Cars &car)
{
if (car.head.x == -1 || car.head.y == -1 || car.head.x == filed.width || car.head.y == filed.height + 1)
{
IzField(filed, car);
}
return false;
}
void main()
{
srand(time(NULL));
Cars car;
BadCar BadCar;
Filed filed;
StartGame(filed, car);
while (true) {
PrintFiled(filed, car, BadCar);
KeyPressEvent(car);
move(filed, car);
if (IsField(filed, car))
{
break;
}
Sleep(200);
}
}
Так, поехали)
1) "если заезжает за правую сторону карты, выезжает с слевой, а если к левой едит, то просто прижимается"
Проерка движения у вас сделана в функции IsField(...), если развернуть вложенную функцию IzField(), то получим следующие проверки движения:
bool IsField(Filed &filed, Cars &car)
{
if (car.head.x == -1 || car.head.y == -1 || car.head.x == filed.width || car.head.y == filed.height + 1)
{
IzField(filed, car); // car.head.x = STOP;
}
}
словами: если координаты машины выходят за границы поля, то в функции IzField мы присваиваем координате х значение STOP, равное 0.
Таким образом получается, что когда машина доезжает до правой рамки, её координата становится 0 и она продолжает движение с этой координаты, что выглядит как будто она заехала справа и выехала слева игрового поля.
Я не знаю, какое поведение вы закладывали, возможно там должно быть
car.dir = STOP
Тогда при достижении границ машина будет останавливаться.
Если же хоите,чтобы машина ездила как пакман, то можно написать так:
bool IsField(Filed &filed, Cars &car)
{
if (car.head.x == -1)
car.head.x = filed.width - 1;
else
if (car.head.x == filed.width)
car.head.x = 0;
if (car.head.y == -1)
car.head.y = filed.height - 1;
else
if (car.head.y == filed.width)
car.head.y = 0;
return false;
}
Тогда машина по достижении какой-либо из границ будет продолжать движение с другой стороны.
2) вызов system("cls");
вызывает адское мерцание, чтобы немного его уменьшить надо вместо system("cls");
использовать вот эту команду SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), COORD{0, 0});
Вкратце, system("cls"); очень неэффективная функция. Вам для отрисовки поля нет нужды каждый раз очищать консоль, можно просто выводить символы поверх предыдущих, а чтобы отрисовывалось нормально необходимо каждый раз перед отрисовкой помещать курсор консоли в начальную позицию. Именно это и делает команда SetConsoleCursorPosition
На самом деле существуют и более изощренные техники отрисовки, полностью исключающие мерцание, гуглите сами.
3) Отрисовка.
Алгоритм отрисовки немного кривой и получается непонятное поле с выбоиной в том месте, где находится игрок.
for (int i = 0; i < filed.height/* + 2*/; i++)
{
for (int j = 0; j < filed.width/* + 2*/; j++)
{
if (j == 0)
{
cout <<(char)179;
}
if (car.head.x == j && car.head.y == i)
{
cout << '*';
continue; // Вот тут!
}
if (_BadCar.head.x == j && _BadCar.head.y == i)
{
cout << "=";
}
else
{
bool IsPrintTail = false;
if (!IsPrintTail)
{
cout << " ";
}
}
if (j == filed.width - 1)
{
cout <<(char)179;
}
}
cout << "\n";
}
Выбоина в поле получалась из-за того, что при отрисовке строки с игроком вы в этой строке отрисовывали и игрока и символ пробела, что в итоге делало размер этой строки больше на 1 символ, чем необходимо, дополнительно я убрал +2, хз зачем оно)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Нужно определить высоту узлаДумаю, нужно при помощи функции обхода дерева подсчитать высоту, вот только с реализацией проблемы
Возникла проблемаЯ изучил абсолютно все, что смог найти
Определенное количество кнопок создается с помощью Repeater(ListModel)Как обратится к определенной кнопки и узнать ее параметры(X, Y)? main