Napisałem grę xonix w c++ z użyciem biblioteki sfml, ale nie potrafię jej uruchomić. Nie wyskakują żądne błędy i nie wiem co jest nie tak, ponieważ mechanika nie działa tak jak powinna. W programie są 3 klasy kolejno po sobie dziedziczące Enemy Player i Game. Klasa Game posiada metodę run, która z założenia miała po wywołaniu jej w funkcji main, uruchomić cały program.
Game.cpp
#include<SFML/System/Clock.hpp>
#include<SFML/System/Time.hpp>
#include"Game.h"
#include "Player.h"
Game::Game() {
game_window.create(sf::VideoMode(K * tile_size, W * tile_size), "XONIX"); // tworzenie okna
game_window.setFramerateLimit(60);
resetGame();
set_frame();
Render();
Run();
}
void Game::resetGame() {
gPlayer.user_x = 0;
gPlayer.user_y = 0;
gPlayer.user_dx = 0;
gPlayer.user_dy = 0;
gameplay = true;
// Reset grid
set_frame();
occupiedCount = -90;
calculateOccupiedPercentage();
// Reset enemies
for (int i = 0; i < numEnemies; i++) {
new enemy(); // Reinitialize enemies
}
}
float Game::calculateOccupiedPercentage() {
occupiedCount = -90.0;
int totalCount = ((W - 2) * (K - 2)) - 27; // Pomijamy obramowanie i miejsce na procenty
for (int i = 0; i < W - 1; i++) {
for (int j = 0; j < K - 1; j++) {
if (grid[i][j] == 1) occupiedCount++;
}
}
float occupiedPercentage = (occupiedCount / static_cast<float>(totalCount)) * 100.0f;
if (static_cast<int>(occupiedPercentage) > 80) {
// game_window.draw(sLevel_up);
resetGame();
}
return occupiedPercentage;
}
void Game::set_frame() {
for (int i = 0; i < W; i++) {
for (int j = 0; j < K; j++) {
if (i == 0 || j == 0 || i == W - 1 || j == K - 1) {
grid[i][j] = 1; // ustawianie wartości 1 w tablicy dla obramowania
}
else {
grid[i][j] = 0; // ustawianie wartości 0 w tablicy dla pustych pól
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 10; j++) {
grid[i][j] = 1; // ustawianie wartości 1 w tablicy dla percentage bar
}
}
}
void Game::Render() {
Texture texture1, texture2, texture3, texture4,texture5; // loading textures
texture1.loadFromFile("images/tiles.png");
texture2.loadFromFile("images/gameover.png");
texture3.loadFromFile("images/enemy.png");
texture4.loadFromFile("images/level_up.png");
Sprite sTile(texture1), sGameover(texture2), sEnemy(texture3), sLevel_up(texture4), sPlayer(texture5);
sLevel_up.setOrigin(100, 100);
sGameover.setPosition(100, 100);
sEnemy.setOrigin(20, 20);
Font font;
if (!font.loadFromFile("font/agency_fb.ttf")) {
std::cerr << "Nie udało się załadować czcionki!" << std::endl;
}
Text percentageText;
percentageText.setFont(font);
percentageText.setCharacterSize(30);
percentageText.setFillColor(Color::White);
percentageText.setStyle(sf::Text::Bold);
percentageText.setPosition(10, 10);
float occupiedPercentage = calculateOccupiedPercentage();
percentageText.setString("Occupied: " + std::to_string(static_cast<int>(occupiedPercentage)) + "%");
game_window.draw(percentageText);
////////////////////////////////////////////////////////////////////////
set_frame();
for (int i = 0; i < W; i++) { // rysuje siatke, przeciwnikow i postac gracza
for (int j = 0; j < K; j++) {
if (grid[i][j] == 0) continue; // puste pole
if (grid[i][j] == 1) sTile.setTextureRect(IntRect(0, 0, tile_size, tile_size)); // sciana
if (grid[i][j] == 2) sTile.setTextureRect(IntRect(54, 0, tile_size, tile_size)); // slad gracza
sTile.setPosition(static_cast<float>(j * tile_size), static_cast<float>(i * tile_size));
game_window.draw(sTile);
}
}
sTile.setTextureRect(IntRect(36, 0, tile_size, tile_size));
sTile.setPosition(user_x * tile_size, user_y * tile_size);
game_window.draw(sTile);
RectangleShape black_bar(sf::Vector2f(162, 54));
black_bar.setFillColor(sf::Color::Black);
black_bar.setPosition(0, 0);
game_window.draw(black_bar);
sEnemy.rotate(10);
for (int i = 0; i < numEnemies; i++) {
sEnemy.setPosition(static_cast<float>(tab[i].x), static_cast<float>(tab[i].y));
game_window.draw(sEnemy);
}
game_window.draw(percentageText);
}
void Game::Run() {
//game_window.create(sf::VideoMode(K * tile_size, W * tile_size), "XONIX"); // tworzenie okna
//game_window.setFramerateLimit(60);
while (game_window.isOpen()) {
while (game_window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
game_window.close();
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Space) {
resetGame();
}
}
}
// Aktualizujemy stan gry
gPlayer.clock.restart();
gPlayer.Move();
gPlayer.collisions();
for (int i = 0; i < numEnemies; i++) {
tab[i].move();
}
// Sprawdzanie kolizji gracza z przeciwnikami
for (int i = 0; i < numEnemies; i++) {
if (grid[tab[i].y / tile_size][tab[i].x / tile_size] == 2) {
gameplay = false;
}
}
if (!gameplay) {
game_window.clear();
// game_window.draw(sGameover);
game_window.display();
//sf::sleep(sf::seconds(2)); // Krótka pauza po zakończeniu gry
resetGame();
continue;
}
// Renderowanie gry
game_window.clear();
Render();
game_window.display();
}
}
ale po jej wywołaniu, obiekt player nawet się nie pokazuje a obiekty enemy wylatują poza okno. Poniżej załączam resztę kodu
Game.h
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include<SFML/System/Time.hpp>
#include <time.h>
#include <iostream>
#include"Player.h"
extern enemy tab[5];
using namespace sf;
class Game: public Player
{
public:
//Sprite sTile, sGameover, sEnemy, sLevel_up;
float occupiedCount=0;
sf::RenderWindow game_window;
sf::Event event;
Game();
void resetGame();
float calculateOccupiedPercentage();
void set_frame();
//void Draw();
void Render();
void Run();
Player gPlayer;
enemy gEnemy;
};
Player.h
#pragma once
#include <time.h>
#include<Windows.h>
#include<sfml/Window.hpp>
#include"enemy.h"
extern int grid[25][40];
extern int tile_size;
class Game;
extern enemy tab[5];
class Player: public enemy
{
public:
int user_dx, user_dy, user_x, user_y;
sf::Clock clock;
float timer = 0;
double delay = 0.07;
Player();
void Move();
void collisions();
int send_components();
static const int W = 25;
static const int K = 40;
};
Player.cpp
#include "Player.h"
#include<SFML/Window.hpp>
#include<windows.h>
using namespace sf;
Player::Player()
{
user_x = 0, user_y = 0, user_dx = 0, user_dy = 0;
srand(static_cast<int>(time(NULL)));
float time = clock.getElapsedTime().asSeconds();
clock.restart();
timer += time;
}
void Player::Move()
{
if (Keyboard::isKeyPressed(Keyboard::Left)) { user_dx = -1; user_dy = 0; } // ruchy gracza
if (Keyboard::isKeyPressed(Keyboard::Right)) { user_dx = 1; user_dy = 0; }
if (Keyboard::isKeyPressed(Keyboard::Up)) { user_dx = 0; user_dy = -1; }
if (Keyboard::isKeyPressed(Keyboard::Down)) { user_dx = 0; user_dy = 1; }
if (timer > delay) // przesuwanie gracza o jedno pole co jakis czas
{
user_x += user_dx;
user_y += user_dy;
if (user_x < 0) user_x = 0;
if (user_y < 0) user_y = 0;
if (user_x > K - 1) user_x = K - 1;
if (user_y > W - 1) user_y = W - 1;
if (grid[user_y][user_x] == 2) gameplay = false; // kolizja w wlasnym sladem
if (grid[user_y][user_x] == 0) grid[user_y][user_x] = 2; // tworzenie sladu
timer = 0;
}
}
void Player::collisions() {
if (grid[user_y][user_x] == 1) // sprawdza czy gracz zamknął obszar i aktualizuje siatke
{
user_dx = user_dy = 0;
for (int i = 0; i < numEnemies; i++)
tab[i].occupy(tab[i].y / tile_size, tab[i].x / tile_size);
for (int i = 0; i < W; i++)
for (int j = 0; j < K; j++)
if (grid[i][j] == -1) grid[i][j] = 0; // obszar zamnkniety
else grid[i][j] = 1; // sciany
}
}
int Player::send_components()
{
return user_x, user_y, user_dx, user_dy;
}
enemy.h
#pragma once
#include<time.h>
#include <stdlib.h>
static int grid[25][40] = { 0 };
static int tile_size=18;
class enemy{
public:
static bool gameplay;
int x, y, dx, dy;
int numEnemies = 5; // number of enemies
enemy();
void move();
void occupy(int y, int x);
~enemy() = default;
};
static enemy tab[5];
enemy.cpp
#include "enemy.h"
bool enemy::gameplay=1;
enemy::enemy()
{
x = 300;
y = 300;
dx = 3- rand() % 6;
dy = 3-rand() % 6;
void move();
}
void enemy::move()
{
x += dx;
if (grid[y / tile_size][x / tile_size] == 1) { dx = -dx; x += dx; }
y += dy;
if (grid[y / tile_size][x / tile_size] == 1) { dy = -dy; y += dy; }
}
//zajmowanie planszy
void enemy::occupy(int y, int x)
{
if (grid[y][x] == 0) grid[y][x] = -1;
if (grid[y - 1][x] == 0) occupy(y - 1, x);
if (grid[y + 1][x] == 0) occupy(y + 1, x);
if (grid[y][x - 1] == 0) occupy(y, x - 1);
if (grid[y][x + 1] == 0) occupy(y, x + 1);
}
Funkcja main to tylko zdefiniowanie obiektu game klasy Game i wywołanie dla niego metody Run().
Byłbym bardzo wdzięczny, gdyby ktoś chociaż podpowiedział gdzie szukać błędów, bo siedzę nad tym już naprawdę długo a na nic nie wpadłem.