Obsługa "strzelania" w C++

0

Witam wszystkich serdecznie! Piszę swoją pierwszą grę i chciałbym Was prosić o podpowiedź. Wprowadziłem obsługę klawiatury i chciałem na podobnej zasadzie obsłużyć też funkcję strzelania. Jednak jeśli próbuję zrobić to analogicznie do wyżej wspomnianego poruszania się z tym że w pętli po każdym przesunięciu wykonuję opóźnienie pętli o 1 sekundę za pomocą Sleep(1000) jednakże "pocisk" zamiast przesuwać się co sekundę wyżej "stoi" w miejscu i dopiero po odczekaniu odpowiedniej ilości sekund znajduje się w pożądanym miejscu :/ . Fragment który próbowałem napisać z wykorzystaniem sleep'a jest pogrubiony i zakomentowany w funkcji void p_tank::move(). Z góry dziękuję za wszelką podpowiedź ;) . Poniżej zamieszczam kod:

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <iostream>
#include <conio.h>
#include <windows.h>


using namespace std;

int const w = 40;
int const h = 30;

struct tank_pos
{
	int x, y;
};

class Map
{
	int **map;
public:
	Map();
	void draw();
	void put_player(tank_pos&);
	void put_shot(tank_pos&);
	void reset();
	~Map();
};

class p_tank
{
	tank_pos player;
	tank_pos shot;
	int kierunek;
public:
	p_tank();
	tank_pos& pozycja_czolgu();
	void move();
	~p_tank();
};


Map::Map()
{
	map = new int*[h];
	for (int i = 0; i < h; ++i) {
		map[i] = new int[w];
	}
	for (int i = 0; i < h;i++)
	for (int j = 0; j < w; j++)
		map[i][j] = 0;
}

void Map::draw()
{
	for (int i = 0; i < h; i++)
	{
		for (int j = 0; j < w; j++)
		{
			switch (map[i][j])
			{
			case 0:
				cout << " ";
				break;
			case 1:
				cout << "T";
				break;
			case 2:
				cout << "*";
				break;
			}
		}
		cout << endl;
	}
}

void Map::put_player(tank_pos &player) 
{
	map[player.x][player.y] = 1;
}


void Map::reset()
{
	for (int i = 0; i < h; i++)
	for (int j = 0; j < w; j++)
		map[i][j] = 0;
}

Map::~Map()
{
	if (map)
	{
		delete[] map;
		map = NULL;
	}
}

p_tank::p_tank()
{
	player.x = 29;
	player.y = 20;
}

tank_pos& p_tank::pozycja_czolgu()
{
	return player;
}



void p_tank::move()
{
	switch (getch())
	{
		case 'w':
			**/*for (int i = player.x; i > 25; i--)
			{
				Sleep(1000);
				player.x--;
			}*/**
			
			if (player.x - 1 == -1)
				break;
			else
				player.x--;
			kierunek = 1;
			break;
		case 's':
			if (player.x + 1 == h)
				break;
			else
				player.x++;
			kierunek = 2;
			break;
		case 'a':
			if (player.y - 1 == -1)
				break;
			else
				player.y--;
			kierunek = 3;
			break;
		case 'd':
			if (player.y + 1 == w)
				break;
			else
				player.y++;
			kierunek = 4;
			break;
	}
}

p_tank::~p_tank()
{
}

int _tmain(int argc, _TCHAR* argv[])
{
	Map mapa;
	p_tank T;
	for (;;)
	{
		mapa.reset();
		mapa.put_player(T.pozycja_czolgu());
		mapa.draw();
		T.move();
		system("cls");
	}
	system("PAUSE");
	return 0;
}
0

Może to dla tego że jeszcze nie zaimplementowałeś tego pocisku.

0

tak wiem ale to dlatego że próbowałem to "rozgryźć" na czymś co działa. Innymi słowy po naciśnięciu klawisza 'w' obiekt T powinien sie przesuwać w górę dopóki i > 25, a teraz działa w ten sposób że czeka tam 4/5 sekund i dopiero pojawia się w określonym miejscu. Nie mogę uzyskać animacji lecącego pocisku.

0

Czy w trakcie lotu pocisku ten twój tank może się poruszać czy nie?

0

Myślę że powinien ale najpierw chciałem się skupić na samej animacji :)

0

twoja funkcja move powinna sprawdzać poprzez kbhit czy coś wciśnięto.
Jeżeli tak to pobrać klawisz poprzez getch i go obsłużyć.
Jeżeli nie - to pomijasz całego switch'a
Po switch w pętle (bo może być wiele lecących pocisków) przesuwasz wszystkie pociski o jakiś krok bliżej celu.
Po czym dajesz sleep na jakieś 100 ms (to tylko 10 klatek na sekundę).

0

hmmmmm masz na myśli coś takiego:
(na razie dalej interpretuję że czołg to pocisk :P i po naciśnięciu 'w' powinien przesuwać się w górę co 100ms )

void p_tank::move()
{
	if(kbhit)
	{
		switch (getch())
		{
		
			case 'w':
				for (int i = player.x; i > 0; i--)
				{	
					player.x--;
					Sleep(100);
				
				}break;
		/*	if (player.x - 1 == -1)
				break;
			else
				player.x--;
			kierunek = 1;
			break;*/
			case 's':
				if (player.x + 1 == h)
					break;
				else
					player.x++;
				kierunek = 2;
				break;
			case 'a':
				if (player.y - 1 == -1)
					break;
				else
					player.y--;
				kierunek = 3;
				break;
			case 'd':
				if (player.y + 1 == w)
					break;
				else
					player.y++;
				kierunek = 4;
				break;
		}	
	}
}

tylko że teraz też nie widać jak ten pocisk przelatuje przez mape :/

0

void Map::draw() ma uwzględniać wszystkie pociski.

0

no tak obiekt który powinien się przesuwać przesyłam przez referencję do klasy map nadaje mu wartość 1 i przeszukuję całą tablicę w poszukiwaniu 0 i 1 i nadaje im znak graficzny. Wiem że gdzieś tam jest błąd ale nie mogę go dostrzec i dlatego bardzo proszę o jakąś dokładniejszą wskazówkę :)

1

To bardzo proste, idziesz na forum wróżbitów i dostajesz wskazówkę, tu niestety nie ma takich wybitnych talentów więc trzeba pokazać kod.

0

Wrzucam ponownie pełny kod: :)

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <iostream>
#include <conio.h>
#include <windows.h>


using namespace std;

int const w = 40;
int const h = 30;

struct tank_pos
{
	int x, y;
};

class Map
{
	int **map;
public:
	Map();
	void draw();
	void put_player(tank_pos&);
	void put_shot(tank_pos&);
	void reset();
	~Map();
};

class p_tank
{
	tank_pos player;
	tank_pos shot;
	int kierunek;
public:
	p_tank();
	tank_pos& pozycja_czolgu();
	void move();
	~p_tank();
};


Map::Map()
{
	map = new int*[h];
	for (int i = 0; i < h; ++i) {
		map[i] = new int[w];
	}
	for (int i = 0; i < h;i++)
	for (int j = 0; j < w; j++)
		map[i][j] = 0;
}

void Map::draw()
{
	for (int i = 0; i < h; i++)
	{
		for (int j = 0; j < w; j++)
		{
			switch (map[i][j])
			{
			case 0:
				cout << " ";
				break;
			case 1:
				cout << "T";
				break;
			}
		}
		cout << endl;
	}
}

void Map::put_player(tank_pos &player) 
{
	map[player.x][player.y] = 1;
}


void Map::reset()
{
	for (int i = 0; i < h; i++)
	for (int j = 0; j < w; j++)
		map[i][j] = 0;
}

Map::~Map()
{
	if (map)
	{
		delete[] map;
		map = NULL;
	}
}

p_tank::p_tank()
{
	player.x = 29;
	player.y = 20;
}

tank_pos& p_tank::pozycja_czolgu()
{
	return player;
}



void p_tank::move()
{
	if(kbhit)
	{
		switch (getch())
		{
		
			case 'w':
				for (int i = player.x; i > 0; i--)
				{	
					player.x--;
					Sleep(100);
				
				}break;
		/*	if (player.x - 1 == -1)
				break;
			else
				player.x--;
			kierunek = 1;
			break;*/
			case 's':
				if (player.x + 1 == h)
					break;
				else
					player.x++;
				kierunek = 2;
				break;
			case 'a':
				if (player.y - 1 == -1)
					break;
				else
					player.y--;
				kierunek = 3;
				break;
			case 'd':
				if (player.y + 1 == w)
					break;
				else
					player.y++;
				kierunek = 4;
				break;
		}	
	}
}

p_tank::~p_tank()
{
}

int _tmain(int argc, _TCHAR* argv[])
{
	Map mapa;
	p_tank T;
	for (;;)
	{
		mapa.reset();
		mapa.put_player(T.pozycja_czolgu());
		mapa.draw();
		T.move();
		system("cls");
	}
	system("PAUSE");
	return 0;
}
0
  1. Wywal pętle pod 'w', tam musisz jedynie zanotować cel pocisku oraz aktualną pozycje pocisku w składowych klasy.
  2. Nadal draw nie rysuje żadnego pocisku.
  3. Nadal move nie przesuwa żadnego pocisku.
0

nie no własnie jak ogarne zasade to dopisze odpowiednie metody na razie chciałbym żeby po wciśnięciu akurat 'w' tank przesuwał się w górę cały czas o jedną wartość i żeby ten ruch był widoczny ;)

0

Nie rozumiem, oczekujesz że ktoś za ciebie to zrobi?

0

W życiu!! chciałbym tylko podpowiedź uzyskać dlaczego jak wcisne 'w' to program nie działa tak że tank przesuwa się co 100ms ku górze o jedną wartość. Jeśli uda mi się uzysakć coś takiego to bez problemu dopisze sobie metody do strzału.

0

Tak dzieje się dla tego że masz pętle wewnątrz której nic się nie rysuje tylko zmienia się player.x, dopiero po zakończeniu pętli następuje jakieś rysowanie.

0

hmm no tak a masz jakiś pomysł jak przed każdą dekrementacją przesyłać aktualną pozycję do funkcji draw???

0

Jak to naprawić podałem wcześniej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1