Switching to sfml
This commit is contained in:
parent
4536c62dad
commit
de72aead56
40 changed files with 462 additions and 2385 deletions
21
src/Enemy/Enemy.cpp
Normal file
21
src/Enemy/Enemy.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "Enemy.hpp"
|
||||
|
||||
Enemy::Enemy(sf::Vector2f position) : rectangle(sf::Vector2f{100, 100})
|
||||
{
|
||||
rectangle.move(position);
|
||||
rectangle.setFillColor(sf::Color::Red);
|
||||
}
|
||||
|
||||
void Enemy::look_at(sf::Vector2f target)
|
||||
{
|
||||
float dx = target.x - rectangle.getPosition().x;
|
||||
float dy = target.y - rectangle.getPosition().y;
|
||||
|
||||
float angle = atan2(dy, dx);
|
||||
rectangle.setRotation(sf::degrees(angle));
|
||||
}
|
||||
|
||||
void Enemy::draw(sf::RenderTarget& target, const sf::RenderStates states) const
|
||||
{
|
||||
target.draw(rectangle, states);
|
||||
}
|
13
src/Enemy/Enemy.hpp
Normal file
13
src/Enemy/Enemy.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
class Enemy : public sf::Drawable
|
||||
{
|
||||
sf::RectangleShape rectangle;
|
||||
public:
|
||||
explicit Enemy(sf::Vector2f position);
|
||||
|
||||
void look_at(sf::Vector2f target);
|
||||
|
||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
};
|
46
src/Game.cpp
Normal file
46
src/Game.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "Game.hpp"
|
||||
|
||||
Game::Game(sf::RenderWindow& window) : window(window)
|
||||
{
|
||||
enemies.emplace_back(sf::Vector2f{100, 100});
|
||||
enemies.emplace_back(sf::Vector2f{200, 200});
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
void Game::run()
|
||||
{
|
||||
std::cout << "Loading map... Version: " MAP_VERSION_STRING << std::endl;
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto err = map.load(ASSETS_PATH "/test.cymf");
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto milliseconds = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
std::cout << "Loading took: " << milliseconds << std::endl;
|
||||
if (err.code != 0)
|
||||
{
|
||||
std::cout << err.message << std::endl;
|
||||
return;
|
||||
}
|
||||
map.debug();
|
||||
while (window.isOpen())
|
||||
{
|
||||
while (const auto event = window.pollEvent())
|
||||
{
|
||||
if (event->is<sf::Event::Closed>())
|
||||
{
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render game
|
||||
window.clear({0x20, 0x20, 0x20,0xff});
|
||||
|
||||
for (auto& enemy : enemies)
|
||||
{
|
||||
window.draw(enemy);
|
||||
}
|
||||
window.draw(map);
|
||||
|
||||
window.display();
|
||||
}
|
||||
}
|
20
src/Game.hpp
Normal file
20
src/Game.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "Enemy/Enemy.hpp"
|
||||
#include "Map/Map.hpp"
|
||||
|
||||
#include <vector>
|
||||
class Game
|
||||
{
|
||||
std::vector<Enemy> enemies;
|
||||
Map map;
|
||||
public:
|
||||
explicit Game(sf::RenderWindow& window);
|
||||
|
||||
void run();
|
||||
private:
|
||||
sf::RenderWindow& window;
|
||||
};
|
||||
|
162
src/Map/Map.cpp
Normal file
162
src/Map/Map.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include "Map.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
Map::Map() {}
|
||||
|
||||
bool operator&(uint8_t lhs, MapFlags rhs)
|
||||
{
|
||||
return lhs & static_cast<uint8_t>(rhs);
|
||||
}
|
||||
|
||||
bool operator==(int lhs, TileType rhs)
|
||||
{
|
||||
return lhs == static_cast<int>(rhs);
|
||||
}
|
||||
|
||||
auto operator<=>(int lhs, TileType rhs)
|
||||
{
|
||||
return lhs <=> static_cast<int>(rhs);
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
MapError Map::load(const std::filesystem::path& path)
|
||||
{
|
||||
// opening the file and checking the magic number
|
||||
std::ifstream file(path, std::ios::binary | std::ios::in);
|
||||
char magic[4];
|
||||
file.read(magic, 4);
|
||||
|
||||
if (std::memcmp(magic, "CYMF", 4) != 0) {
|
||||
return {"Map: [Loading] Invalid magic number", 1};
|
||||
}
|
||||
|
||||
// reading the version
|
||||
uint8_t version[3];
|
||||
file.read(reinterpret_cast<char*>(version), 3);
|
||||
if (version[0] != MAP_VERSION_MAJOR || version[1] > MAP_VERSION_MINOR)
|
||||
{
|
||||
return {"Map: [Loading] Invalid version; Current: " MAP_VERSION_STRING, 1};
|
||||
}
|
||||
|
||||
// reading the flags
|
||||
uint8_t flags;
|
||||
file.read(reinterpret_cast<char*>(&flags), 1);
|
||||
|
||||
// flag CustomTilemap -> load the tilemap
|
||||
if (flags & MapFlags::CustomTilemap)
|
||||
{
|
||||
uint32_t filepath_buffer_size;
|
||||
file.read(reinterpret_cast<char*>(&filepath_buffer_size), 4);
|
||||
|
||||
char* filepath_buffer = new char[filepath_buffer_size];
|
||||
file.read(filepath_buffer, filepath_buffer_size);
|
||||
|
||||
tileAtlas.load(std::filesystem::path(filepath_buffer));
|
||||
delete[] filepath_buffer;
|
||||
}
|
||||
|
||||
|
||||
// load the map info
|
||||
uint32_t map_info[3];
|
||||
file.read(reinterpret_cast<char*>(map_info), 12);
|
||||
map_size = sf::Vector3<size_t>(static_cast<size_t>(map_info[0])*map_info[1], map_info[0], map_info[1]);
|
||||
|
||||
// load the tiles
|
||||
tiles = new int[map_info[0] * map_info[1] + map_info[2] * (sizeof(MapSpecial)/4)];
|
||||
for (int i = 0; i < map_info[0] * map_info[1] + map_info[2] * (sizeof(MapSpecial)/4); i++)
|
||||
{
|
||||
// read the special if needed
|
||||
file.read(reinterpret_cast<char*>(&tiles[i]), 4);
|
||||
if (tiles[i] == TileType::Special)
|
||||
{
|
||||
MapSpecial special{};
|
||||
file.read(reinterpret_cast<char*>(&special), sizeof(MapSpecial));
|
||||
// get position
|
||||
uint32_t tile_x = i % map_info[0];
|
||||
uint32_t tile_y = i / map_info[0];
|
||||
specials.emplace_back(std::pair<sf::Vector2u, MapSpecial>({tile_x, tile_y}, special));
|
||||
}
|
||||
}
|
||||
|
||||
// load the player spawn
|
||||
uint32_t t_player_spawn[2];
|
||||
file.read(reinterpret_cast<char*>(t_player_spawn), 8);
|
||||
player_spawn = sf::Vector2u{t_player_spawn[0], t_player_spawn[1]};
|
||||
if (player_spawn.x >= map_size.y || player_spawn.y >= map_size.z)
|
||||
{
|
||||
return {"Map: [Loading] Player: Spawn out of bounds", 2};
|
||||
}
|
||||
int player_tile = tiles[player_spawn.x + player_spawn.y * map_size.x];
|
||||
if (player_tile <= TileType::Special)
|
||||
{
|
||||
return {"Map: [Loading] Player: Spawn is not a valid tile (invalid: wall, special; valid: Floor)", 2};
|
||||
}
|
||||
|
||||
// load all the enemy spawns
|
||||
uint32_t number_enemy_spawns;
|
||||
file.read(reinterpret_cast<char*>(&number_enemy_spawns), 4);
|
||||
if (number_enemy_spawns > map_size.x)
|
||||
{
|
||||
return {"Map: [Loading] Enemies: Too many enemy spawns (More than tile in the map)", 3};
|
||||
}
|
||||
for (int i = 0; i < number_enemy_spawns; i++)
|
||||
{
|
||||
uint32_t t_enemy_spawn[2];
|
||||
file.read(reinterpret_cast<char*>(t_enemy_spawn), 8);
|
||||
if (t_enemy_spawn[0] >= map_size.x || t_enemy_spawn[1] >= map_size.y)
|
||||
{
|
||||
return {"Map: [Loading] Enemy: Spawn out of bounds", 4};
|
||||
}
|
||||
if (tiles[t_enemy_spawn[0] + t_enemy_spawn[1] * map_size.y] <= TileType::Special)
|
||||
{
|
||||
return {"Map: [Loading] Enemy: Spawn is not a valid tile (invalid: wall, special; valid: Floor)", 4};
|
||||
}
|
||||
if (t_enemy_spawn[0] == player_spawn.x && t_enemy_spawn[1] == player_spawn.y)
|
||||
{
|
||||
return {"Map: [Loading] Enemy: Spawn is the same as the player spawn", 4};
|
||||
}
|
||||
enemy_spawns.emplace_back(t_enemy_spawn[0], t_enemy_spawn[1]);
|
||||
}
|
||||
|
||||
// Everything went well
|
||||
return {"Map: [Loading] Success", 0};
|
||||
}
|
||||
|
||||
sf::Vector2u Map::getSize() const
|
||||
{
|
||||
return {static_cast<uint32_t>(map_size.y), static_cast<uint32_t>(map_size.z)};
|
||||
}
|
||||
|
||||
void Map::draw(sf::RenderTarget& target, const sf::RenderStates states) const
|
||||
{
|
||||
if (!tiles) return;
|
||||
for (uint32_t x = 0; x < map_size.y; x++) {
|
||||
for (uint32_t y = 0; y < map_size.z; ++y)
|
||||
{
|
||||
target.draw(tileAtlas, states);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void Map::debug()
|
||||
{
|
||||
std::cout << "Map Debug" << std::endl;
|
||||
std::cout << "\tSize : " << map_size.x << ", " << map_size.y << ", " << map_size.z << std::endl;
|
||||
std::cout << "\tTiles : 0x" << tiles << std::endl;
|
||||
for (auto& special : specials)
|
||||
{
|
||||
std::cout << "\t\tSpecial : " << special.first.x << ", " << special.first.y << std::endl;
|
||||
std::cout << "\t\t\tType : " << special.second.type << std::endl;
|
||||
std::cout << "\t\t\tPortal : " << special.second.portal_end[0] << ", " << special.second.portal_end[1] << std::endl;
|
||||
}
|
||||
std::cout << "\t\tEnemy Spawns : " << enemy_spawns.size() << std::endl;
|
||||
for (auto& spawn : enemy_spawns)
|
||||
{
|
||||
std::cout << "\t\t\tSpawn : " << spawn.x << ", " << spawn.y << std::endl;
|
||||
}
|
||||
std::cout << "\t\tPlayer Spawn : " << player_spawn.x << ", " << player_spawn.y << std::endl;
|
||||
}
|
101
src/Map/Map.hpp
Normal file
101
src/Map/Map.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
/******************************************************************
|
||||
* ==============================================================
|
||||
* Map File Format
|
||||
* ==============================================================
|
||||
*
|
||||
* int8_t magic[4] = 'CYMF' (Colysis Map File) : 4 bytes
|
||||
* uint8_t version[3] : major, minor, patch
|
||||
*
|
||||
* uint8_t flags
|
||||
* if (flags):
|
||||
* case MapFlags::CustomTilemap:
|
||||
* uint32_t filepath_buffer_size
|
||||
* char filepath_buffer[filepath_buffer_size]
|
||||
* uint32_t tile_size[2] : width, height
|
||||
* uint32_t tile_count[2] : width, height
|
||||
*
|
||||
* uint32_t map_size[3] : x, y, specials
|
||||
* int32_t tiles[x * y + specials * (sizeof(MapSpecial)/4)] : tilemap data
|
||||
* // a special tile has a type and its tilemap data
|
||||
* if tiles[i] == Special:
|
||||
* uint8_t type
|
||||
* MapSpecial data
|
||||
* else:
|
||||
* uint8_t tile
|
||||
*
|
||||
* uint32_t player_spawn[2] : x, y
|
||||
* uint32_t number_enemy_spawns
|
||||
* uint32_t enemy_spawns[number_enemy_spawns][2] : x, y
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#define STR(name) #name
|
||||
#define STR_VALUE(name) STR(name)
|
||||
|
||||
#define MAP_VERSION_MAJOR 0
|
||||
#define MAP_VERSION_MINOR 1
|
||||
#define MAP_VERSION_PATCH 0
|
||||
#define MAP_VERSION (MAP_VERSION_MAJOR << 16 | MAP_VERSION_MINOR << 8 | MAP_VERSION_PATCH)
|
||||
#define MAP_VERSION_STRING STR_VALUE(MAP_VERSION_MAJOR) "." STR_VALUE(MAP_VERSION_MINOR) "." STR_VALUE(MAP_VERSION_PATCH)
|
||||
|
||||
|
||||
struct MapSpecial
|
||||
{
|
||||
int type;
|
||||
uint32_t portal_end[2];
|
||||
};
|
||||
|
||||
enum class MapFlags : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
CustomTilemap = 1 << 0,
|
||||
UNDEFINED = 1 << 1,
|
||||
};
|
||||
|
||||
enum class TileType : int
|
||||
{
|
||||
Wall = -1,
|
||||
Special = 0,
|
||||
Other = 1,
|
||||
};
|
||||
|
||||
|
||||
struct MapError
|
||||
{
|
||||
const char* message;
|
||||
int code;
|
||||
};
|
||||
|
||||
|
||||
#include "TileAtlas.hpp"
|
||||
|
||||
class Map : public sf::Drawable
|
||||
{
|
||||
static_assert(sizeof(MapSpecial)%4 == 0);
|
||||
|
||||
TileAtlas tileAtlas = TileAtlas::defaultAtlas();
|
||||
|
||||
sf::Vector3<size_t> map_size; // width * height, width, height
|
||||
int *tiles = nullptr;
|
||||
|
||||
std::vector<std::pair<sf::Vector2u, MapSpecial>> specials;
|
||||
|
||||
std::vector<sf::Vector2u> enemy_spawns;
|
||||
sf::Vector2u player_spawn;
|
||||
public:
|
||||
Map();
|
||||
|
||||
MapError load(const std::filesystem::path& path);
|
||||
|
||||
sf::Vector2u getSize() const;
|
||||
|
||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
|
||||
void debug();
|
||||
};
|
||||
|
||||
|
41
src/Map/TileAtlas.cpp
Normal file
41
src/Map/TileAtlas.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "TileAtlas.hpp"
|
||||
|
||||
TileAtlas TileAtlas::defaultAtlas()
|
||||
{
|
||||
TileAtlas atlas(sf::Vector2u{16, 16}, sf::Vector2u{16, 16}, ASSETS_PATH "/default_tilemap.png");
|
||||
atlas.sprite.setTexture(atlas.texture);
|
||||
atlas.sprite.setTextureRect(sf::IntRect({0, 0}, {static_cast<int>(atlas.tile_size.x), static_cast<int>(atlas.tile_size.y)}));
|
||||
return atlas;
|
||||
}
|
||||
|
||||
void TileAtlas::set(uint32_t x, uint32_t y)
|
||||
{
|
||||
if (x >= tile_count.x || y >= tile_count.y) return;
|
||||
sprite.setTextureRect(sf::IntRect({static_cast<int>(x * tile_size.x), static_cast<int>(y * tile_size.y)}, sf::Vector2<int>(tile_size)));
|
||||
}
|
||||
|
||||
TileAtlas::TileAtlas(const sf::Vector2u tile_size, const sf::Vector2u tile_count, const std::filesystem::path& path) :
|
||||
tile_size(tile_size), tile_count(tile_count), sprite(texture) { load(path); }
|
||||
|
||||
TileAtlas::TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count) : tile_size(tile_size), tile_count(tile_count), sprite(texture)
|
||||
{
|
||||
}
|
||||
|
||||
void TileAtlas::load(const std::filesystem::path& path)
|
||||
{
|
||||
if (!texture.loadFromFile(path))
|
||||
{
|
||||
throw std::runtime_error("TileAtlas: [Loading] Could not load tilemap -> Fatal");
|
||||
}
|
||||
sprite.setTexture(texture);
|
||||
sprite.setTextureRect(sf::IntRect({0, 0}, {static_cast<int>(tile_size.x), static_cast<int>(tile_size.y)}));
|
||||
}
|
||||
|
||||
void TileAtlas::draw(sf::RenderTarget& target, const sf::RenderStates states) const
|
||||
{
|
||||
if (texture.getSize().x == 0 || texture.getSize().y == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
target.draw(sprite, states);
|
||||
}
|
21
src/Map/TileAtlas.hpp
Normal file
21
src/Map/TileAtlas.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
class TileAtlas : public sf::Drawable
|
||||
{
|
||||
sf::Vector2u tile_size;
|
||||
sf::Vector2u tile_count;
|
||||
sf::Texture texture;
|
||||
sf::Sprite sprite;
|
||||
public:
|
||||
explicit TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count, const std::filesystem::path& path);
|
||||
TileAtlas(sf::Vector2u tile_size, sf::Vector2u tile_count);
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
|
||||
static TileAtlas defaultAtlas();
|
||||
|
||||
void set(uint32_t, uint32_t);
|
||||
|
||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
};
|
71
src/main.c
71
src/main.c
|
@ -1,71 +0,0 @@
|
|||
#include <colysis.h>
|
||||
|
||||
#define RAYLIB_BACKEND
|
||||
|
||||
#include <alyson.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include <raylib.h>
|
||||
|
||||
#include <raymath.h>
|
||||
#include <rlyson.h>
|
||||
|
||||
#include <animation/sprite.h>
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
InitWindow(900, 600, "Colysis");
|
||||
SetWindowState(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_MAXIMIZED);
|
||||
|
||||
|
||||
Texture2D gery = LoadTexture(ASSETS_PATH "/karl-heinz_head.png");
|
||||
|
||||
SpriteAnimation geryanim = CreateSpriteAnimation(gery,
|
||||
(Vector2){64*14,64}, (Vector2){64,64},
|
||||
0.f, 4.f, 5, 0.15f);
|
||||
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){0,0};
|
||||
camera.offset = (Vector2){GetScreenWidth()/2.f,GetScreenHeight()/2.f};
|
||||
camera.rotation = 0.f;
|
||||
camera.zoom = 1.f;
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
ClearBackground((Color){ 0x00, 0x6d, 0xfb });
|
||||
float dt = GetFrameTime();
|
||||
camera.offset = (Vector2){GetScreenWidth()/2.f,GetScreenHeight()/2.f};
|
||||
|
||||
|
||||
UpdateSpriteAnimation(geryanim, dt);
|
||||
|
||||
|
||||
BeginDrawing();
|
||||
{
|
||||
BeginMode2D(camera);
|
||||
{
|
||||
DrawSpriteAnimation(geryanim, (Vector2){0,0});
|
||||
}
|
||||
EndMode2D();
|
||||
|
||||
{
|
||||
DrawTextFull(GetFontDefault(), "Darling, I'm Home!",
|
||||
(Vector2){20,20}, TEXT_ORIENTATION_RIGHT,
|
||||
0, 24, 5, 5, RAYWHITE);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
DestroySpriteAnimation(geryanim);
|
||||
UnloadTexture(gery);
|
||||
|
||||
CloseWindow();
|
||||
|
||||
return 0;
|
||||
}
|
15
src/main.cpp
Normal file
15
src/main.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Window.hpp>
|
||||
|
||||
#include "Game.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
sf::RenderWindow window(sf::VideoMode({800, 450}), "Colysis", sf::Style::Close | sf::Style::Titlebar);
|
||||
window.setMinimumSize(sf::Vector2u{800, 450});
|
||||
|
||||
Game game(window);
|
||||
game.run();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue