Diskuze: Hra tanky
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.


DarkCoder:15.10.2018 18:14
Chceš-li, abychom Ti jakkoli pomohli, je třeba být konkrétnější. Pod pojmem hra "Tanky" si mohu představit mnoho variant. Od klasické 2D akce ala Worms, přes pozemní variantu lodí, tankovou bitvu v bludišti, až po 3D akci ala World of Tanks. Zde vidíš, že možností je spousta. Zadání je komplexnější a předpokládá se, že něco už v C umíš. Tudíž bys měl být schopen sestavit alespoň hlavní kostru programu. A abychom se zapojili i my, je třeba, aby si nám zde prezentoval to co už máš. Tedy svůj kód který si sám zpracoval, na kterém se dá stavět.
Ospravedlňujem sa zabudol som to lepšie špecifikovať.
- Hra má byť na princípe hry Scorched Earth. Po spustení programu má byť umožnení zvoliť si počet hráčov a ich mená.
- Následne sa zo súboru načíta herný plán (pozície tankov možu byť v jednotlivých plánoch pevne dané alebo náhodne generované).
- Tanky sa vo výstreloch pravidelne striedajú a pre výpočet trajektórie strely bude využitá rovnica šikmého vrhu spoločne s následnou aproximáiou k najbližšiemu bodu v matici.
- Ničenie zeme nieje potrebné implementovať, čiže ked strela zasiahne povrch, tak sa nič nestane nedeformuje sa.
Ja som z tohoto programu nespravil ešte nič, vôbec si ani neviem predstaviť ako by to malo vyzerať, preto som sa chcel obrátiť na toto fórum či by sa tu nenašiel niekto, kto by mi ukázal nejakú cestu, nasmeroval ma.
Ještě je otázka, zda se má jednat o grafický program s vizualizací, nebo jen o dialogový program. A v jakém překladači má být vytvořený. Ze zadání mám dojem, že se jedná o konzolový program, tedy by to mohl být celkem jednoduchý program. K překladu buď GCC nebo MS VC++. První krok by byl založení konzolového projektu - dosáhnout toho, aby jsi uměl přeložit a spustit jednoduchý program "int main() { printf("Ahoj"); return 0; }". Potom se naučit používat funkci pro uživatelský vstup scanf - stačí umět převzít text a ten pak vytisknout na obrazovku. V programu by se vytvořilo pole struktur struct, které bude obsahovat pozice tanků a jejich stav poškození. V hlavní funkci main by bylo nejdříve zadání hráčů se scanf a načtení herního plánu (funkce fopen, fread, fclose). Pak by běžela hlavní smyčka for(), ve které se budou obsluhovat jednotlivý hráči: Vypsání stavu hry pro hrajícího hráče (stav jeho tanku, vzdálenosti a stavy nepřátel). Zadání úhlu a síly úderu se scanf. Následuje výpočet místa dopadu a podle toho aktualizace stavu ostatních tanků. Výpis poškození printf a pokračuje opět smyčka pro dalšího hráče.
Luboš Běhounek Satik:15.10.2018 18:47
Nejdriv musis vymyslet, jak budes hru reprezentovat. Teren v takovyhle hre bych resil pres dvourozmerny (jde to i jednorozmernym) pole bodu, kde mas ulozeny, jestli je tam plno/prazdno, pripadne i treba barva pixelu terenu.
Tohle cely potrebujes nejak cyklicky vykreslovat.
Pak budes potrebovat vymyslet, jak reprezentovat jednotlivy hrace/tanky. Takze si pro ne udelat nejspis tridu, kde bude treba barva nebo textura tanku, jmeno, jak ma otocenou hlaven, jak je poskozeny apod.
Ten pak pridas do vykreslovani hned za kresleni terenu.
Pak jeste budou potreba projektily a taky neco pro rizeni hry, kde bude treba ulozeno, ktery hrac je na rade apod.
Pole (nebo treba i vectory) ovladas? Vykreslovat na obrazovku nejak umis?
Luboš Satik Běhounek -> polia sa práve učím, čiže viem zhruba na
akom princípe to pracuje.
Vykreslovanie na obrazovku, neviem čo sa tým myslí, ako výpis niečoho na
obrazovku ?
Zatiaľ vám veľmi pekne ďakujem, už aspoň viem čo si mám na internete pozrieť a ako by som aspoň mal začať.
google = tank game c code
https://www.codewithc.com/…e-c-project/
Kdyz bych omezil nektere podminky, tak se jedna jen o
- poloha tanku, x,y, oblast cile
- otoceni hlavne
- strela, jeji poloha
- detekce kolize s tankem
- detekce kolize se spodni lajnou obrazovky
Pokud si to chces komplikovat, pridej teren, linii pixelu, ktere ho
ohranicuji.
Pri kolizi budes muset upravit cast linie.
Kolizi muzes detekovat podle bodu trajektorie. Pro prvni detekci staci
obdelnicek i, i+1 pixely trajektorie. Pokud nemas trajektorie pixel po pixelu, a
najde-li se mozna kolize, budes muset pristoupit ke zjemneni trajektorie mezi
temito body na pixely a znovu detekovat pro ne kolize.
Uplne jednoduche by mohlo byt, kdyby vzdalenost bodu trajektorie neprekrocila
sirku tanku. Pak ti staci detekovat jen prvni druh kolize s tanky.
Samozrejme, muzes jit zrovna do 1px trajektorie, dnesni pc by to meli zvladnout
https://mlich.zam.slu.cz/x/js-tanks.htm
Takovy pokus. By sis to musel prepsat ale do cecka
Mezerou strili.
Sipkami meni sklon hlavne.
Jsou tam nejake chybky, ktere treba doladit a neni tam pc inteligence. A tusim
ani tank nevybuchne. A taky spoustu promennych navic, protoze jsem prepisoval
jiny kod. Ale jako zaklad by to mohlo byt pouzitelne. (nebo, kdyz leti strela,
zmenis sklon hlavne, tak tam prebiram uhel z playera, coz je taky chyba)
Nicmene skolni projekty neresime za jine.
Mel jsem cas, trochu jsem to upravil. Uz to strili relativne ok.
https://mlich.zam.slu.cz/x/js-tanks.htm
Ahojte, takto som pokročil s kodom, no neviem ako mám v konzolovom okne nastaviť farbu tankom (X su tanky) tak, aby sa zhodovalo s menami, ktoré su napísané vedľa mapy. Napr. že hráč 1 bude červený, tak tak nejaký tank bude červený, potom ďalšie meno bude zelené, tak nejaký tank bude zelený atď. Ďakujem za odpoveď.
// mapa.cpp : Tento soubor obsahuje funkci main. Provádění programu se tam zahajuje a ukončuje.
//
#include "pch.h"
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <math.h>
#include <ctime>
#define WIDTH 63
#define HEIGHT 27
#define M_PI 3.14159265358979323846
#define degreesToRadians(angleDegrees) ((angleDegrees) * M_PI / 180.0) // *180)/3.1415926535897932384626433832795;
#define max 10
typedef struct tank { // uprava do void fukcie a tej do kniznice
char meno[20];
WORD farba = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
int xPoz;
int yPoz;
bool naRade = false;
// HP ; volba generovani nahodne mapy 2- volba mapy ze suboru
};
//funkce pro skryti kursoru v konzoli
void showConsoleCursor(bool showFlag)
{
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(out, &cursorInfo);
cursorInfo.bVisible = showFlag;
SetConsoleCursorInfo(out, &cursorInfo);
}
int **createMatrix(int m, int n) {
int** matrix = new int*[m];
for (int i = 0; i < m; i++)
{
matrix[i] = new int[n];
for (int j = 0; j < n; j++) {
matrix[i][j] = 0;
}
}
return matrix;
};
int loadFromFile(int **matrix, char *filename) {
FILE *file;
fopen_s(&file, filename, "r");
if (file == NULL)
return 1;
char c;
int i = 0;
int j = 0;
while ((c = fgetc(file)) != EOF && i < HEIGHT) {
if (c == '\n') {
i++;
j = 0;
continue;
}
if (j > WIDTH - 1) {
continue;
}
switch (c) {
case '0':
matrix[i][j] = 1;
break;
default:
matrix[i][j] = 0;
}
j++;
}
fclose(file);
return 0;
}
void initMatrix(int **matrix, int rows, int columns, int poceth, tank *hraci) {
int* heights = new int[columns];
heights[0] = (int)rows / 3;
for (int i = 1; i < columns; i++) {
heights[i] = heights[i - 1] + (rand() % 3) - 1;
if (heights[i] < 3) {
heights[i] = 3;
}
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
if (rows - heights[j] >= i) {
matrix[i][j] = 0;
}
else {
matrix[i][j] = 1;
}
/*
for (int k = 0; k < poceth; k++) {
if ((hraci[k].xPoz == j) && ((rows - heights[j]) == i)) {
matrix[i][j] = 2;
hraci[k].yPoz = i;
}
}*/
}
}
}
void printMatrix(int **matrix, int m, int n) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD cur = { 0, 0 };
SetConsoleCursorPosition(hConsole, cur);
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
WORD saved_attributes;
GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
saved_attributes = consoleInfo.wAttributes;
GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
saved_attributes = consoleInfo.wAttributes;
int stringSize = ((n * 2) + 2) * m;
char *matrixString = new char[stringSize];
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
printf("/");
for (int i = 0; i < n; i++) { printf("-"); }
printf("\\\n");
for (int i = 0; i < m; i++)
{
printf("|");
for (int j = 0; j < n; j++)
{
switch (matrix[i][j]) {
case 0: {printf(" "); break; }
case 1: {SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
printf("0");
break; }
case 2: {SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); printf("X"); break; }
case 3: {SetConsoleTextAttribute(hConsole, FOREGROUND_RED); printf("o"); break; }
}
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
printf("|\n");
}
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
printf("\\");
for (int i = 0; i < n; i++) { printf("-"); }
printf("/\n");
}
void printTanks(tank *hraci, int poceth, int columns)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for (int i = 0; i < poceth; i++)
{
COORD cur = { columns + 10, 5 + i };
SetConsoleCursorPosition(hConsole, cur);
if (hraci[i].naRade) {
SetConsoleTextAttribute(hConsole, hraci[i].farba | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY);
}
else {
SetConsoleTextAttribute(hConsole, hraci[i].farba);
}
printf("%s", hraci[i].meno);
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
}
}
float posx(float t, float vx, int x) {
return vx * t + x;
}
float posy(float t, float vy, int y) {
return -(-0.5 * 10 * t*t) - (vy*t) + y;
}
double vx(float v, float angle) {
return v * cos(degreesToRadians(angle));
}
double vy(float v, float angle) {
return v * sin(degreesToRadians(angle));
}
void tankHit(tank *hraci, int *poceth, int x, int y) {
for (int i = 0; i < *poceth; i++) {
if (hraci[i].xPoz == x && hraci[i].yPoz == y) {
for (int j = i + 1; j < *poceth; j++) {
hraci[j - 1] = hraci[j];
}
}
}
(*poceth)--;
}
void ShowConsoleCursor(bool visible)
{
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(out, &cursorInfo);
cursorInfo.bVisible = visible;
SetConsoleCursorInfo(out, &cursorInfo);
}
void shoot(int **matrix, int initx, int inity, float initVelocity, float angle, tank *hraci, int *poceth, int m, int n) {
ShowConsoleCursor(false);
int oldx = 0, oldy = 0;
double velx = vx(initVelocity, angle);
double vely = vy(initVelocity, angle);
float t = 0;
int x = initx;
int y = inity;
int tmpState = 0;
do {
float positx = posx(t, velx, initx);
float posity = posy(t, vely, inity);
x = (int)round(positx);
y = (int)round(posity);
if (y > HEIGHT - 1 || y <= 0 || x > WIDTH - 1 || x <= 0) {
break;
}
if (oldx == x && oldy == y) {
Sleep(20);
t += 0.04;
continue;
}
oldx = x; oldy = y;
switch (matrix[y][x]) {
case 0:
matrix[y][x] = 3;
printMatrix(matrix, m, n);
matrix[y][x] = 0;
break;
case 2:
tmpState = matrix[y][x];
matrix[y][x] = 0;
tankHit(hraci, poceth, x, y);
printMatrix(matrix, m, n);
break;
case 1:
tmpState = matrix[y][x];
matrix[y][x] = 0;
if (matrix[y][x - 1] == 2) {
matrix[y][x - 1] = 0;
matrix[y][x] = 2;
for (int i = 0; i < *poceth; i++) {
if (hraci[i].xPoz == x) {
hraci[i].yPoz = y;
}
}
}
break;
}
Sleep(10);
t += 0.06;
} while (tmpState != 2 && tmpState != 1 && y < HEIGHT - 1 && y >= 0 && x < WIDTH - 1 && x >= 0);
printMatrix(matrix, m, n);
printTanks(hraci, *poceth, n);
ShowConsoleCursor(true);
}
int main()
{
srand((int)time(NULL));
tank hraci[max];
printf("Zadaj pocet hracov : ");
int poceth;
int znak;
do {
poceth = getchar();
} while (poceth < 50 || poceth > 55);
poceth -= 48;
for (int i = 0; i < poceth; i++)
{
printf("\n Zadaj meno %d. hraca :", i + 1);
scanf_s("%s", &hraci[i].meno, 19);
};
for (int i = 0; i < poceth; i++) {
printf("\nhrac %d : %s \n", i + 1, hraci[i].meno);
};
int m, n;
int **matrix;
do {
printf("Vyber si moznost - Stlac 1 pre random mapu alebo Stlac 2 pre nacitanie mapy z 3 vytvorenych: ");
scanf_s("%d", &m);
printf("Zadal si zle cislo, mozes len alebo 2. Zadaj este raz.\n");
} while (m != 1 && m != 2);
if (m == 1) {
printf("zadaj velkost mapy: ");
scanf_s("%d %d", &m, &n);
matrix = createMatrix(m, n);
initMatrix(matrix, m, n, poceth, hraci);
}
else {
char mapa[10] = { "mapaX.txt" };
int randMap = 1;
randMap = rand() % 3 + 1;
mapa[4] = randMap + 48;
m = HEIGHT; n = WIDTH;
matrix = createMatrix(m, n);
if (loadFromFile(matrix, mapa) == 1) {
printf("Mapa %s sa nenasla \n", mapa);
getchar();
return 1;
}
}
system("cls");
for (int i = 0; i < poceth; i++) {
bool zhoda = false;
int x = rand() % n;
for (int j = 0; j < i; j++) {
if (x == hraci[j].xPoz) { zhoda = true; break; }
}
if (!zhoda) {
hraci[i].xPoz = x;
for (int j = 0; j < m; j++) {
if (matrix[j][x] == 0 && matrix[j + 1][x] == 1) {
hraci[i].yPoz = j;
matrix[j][x] = 2;
break;
}
}
}
else {
i--;
}
printf("rand x je : %d\n", x);
}
printMatrix(matrix, m, n);
showConsoleCursor(false);
printTanks(hraci, poceth, n);
int j = 0;
while (poceth > 1) {
for (int i = 0; i < poceth; i++) {
hraci[j].naRade = false;
hraci[i].naRade = true;
j = i;
printMatrix(matrix, m, n);
printTanks(hraci, poceth, n);
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD cur = { n + 10, 15 + poceth };
SetConsoleCursorPosition(hConsole, cur);
float velocity = 0;
float angle = 0;
printf("Zadaj silu strely: ");
scanf_s("%f", &velocity);
cur = { cur.X, cur.Y + 1 };
SetConsoleCursorPosition(hConsole, cur);
printf("Zadaj uhol:");
scanf_s("%f", &angle);
shoot(matrix, hraci[i].xPoz, hraci[i].yPoz - 1, velocity, angle, hraci, &poceth, m, n);
system("cls");
}
}
system("cls");
printf("Vyhral hrac %s, Gratulujeme !\n", hraci[0].meno);
system("pause");
}
// Spuštění programu: Ctrl+F5 nebo nabídka Ladit > Spustit bez ladění
// Ladění programu: F5 nebo nabídka Ladit > Spustit ladění
// Tipy pro zahájení práce:
// 1. K přidání nebo správě souborů použijte okno Průzkumník řešení.
// 2. Pro připojení ke správě zdrojového kódu použijte okno Team Explorer.
// 3. K zobrazení výstupu sestavení a dalších zpráv použijte okno Výstup.
// 4. K zobrazení chyb použijte okno Seznam chyb.
// 5. Pokud chcete vytvořit nové soubory kódu, přejděte na Projekt > Přidat novou položku. Pokud chcete přidat do projektu existující soubory kódu, přejděte na Projekt > Přidat existující položku.
// 6. Pokud budete chtít v budoucnu znovu otevřít tento projekt, přejděte na Soubor > Otevřít > Projekt a vyberte příslušný soubor .sln.
Zobrazeno 10 zpráv z 10.