Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Zlecenie - Kod programu do generowania mapy kafelkowej

Ostatnio zmodyfikowano wczoraj o godz. 22:25
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
Zlecenie - Kod programu do generowania mapy kafelkowej
» 2025-11-14 18:22:40
Zlecę napisanie programu i podanie jego kodu w którym można rysować mapę kafelkową z użyciem różnych tilesetów.
Program ma działać w ten sposób, by dany kafelek był wybierany automatycznie i dopasowany kształtem do sąsiednich kafelków.
Program ma być prosty, bez żadnych dodatków, tylko mapa i paleta z tilesetami.

Może być program napisany w oparciu o ten tileset. Tileset składa się z pól 16px x 16px po cztery w rzędzie (żeby mapa nie była tak bardzo powtarzalna)
https://github.com/tBane1995/Auto-Tiled/blob/main/Auto-Tiled/tex/set_0.png

Proponuję 400zł. Cena do negocjacji.
P-183462
skovv
» 2025-11-14 19:16:04
Hoho jak cena idzie w górę :D Nie wolisz sam napisać? :D
P-183463
tBane
Temat założony przez niniejszego użytkownika
» 2025-11-14 19:18:40
Nie potraafię samemu tego zaprogramować :-/ Próbowałem parę razy podejść na nowo do tego tematu i nie wyszło. W necie też nie ma informcji jak coś takiego zrobić - stąd zlecenie. :-)
P-183464
skovv
» 2025-11-14 19:24:50
Aj tam będziesz płacił - pomyśl jeszcze raz aż wyjdzie! Ja bym to zrobił tak, że pierw ustawiasz sobie tileset. W sensie ładujesz obrazek, ustawiasz w/h klatki no i wtedy możesz sobie dodać "grupe" np trawa, piasek itp. Wtedy w grupie masz główny kafelek, nadajesz ten srodkowy. W gupie daj też możliwość ustawienia bocznych/narożnych kafli. Jak już sobie zedytujesz grupy to po prostu rysujesz wybierając daną grupę zamiast kafla. Rozumiesz? Wtedy jak rysujesz mapę to widzisz że np ten kafel jest ostatnim z brzegu wiec rysujesz kafel ostatni z danego brzegu jaki dalismy do tej grupy i tyle. Rozumiesz o co mi chodzi?
P-183465
tBane
Temat założony przez niniejszego użytkownika
» 2025-11-14 19:25:55
Rozumiem, ale nie wiem jak to zaprogramować. Przydałby się gotowy kod.
P-183466
DejaVu
» 2025-11-14 19:31:43
C/C++
#include <SFML/Graphics.hpp>
#include <vector>
#include <map>
#include <iostream>

// Tile size in pixels
const int TILE_SIZE = 32;

// Map dimensions (in tiles)
const int MAP_WIDTH = 20;
const int MAP_HEIGHT = 15;

// Maximum number of tilesets
const int MAX_TILESETS = 4;

// Tile class to represent a tile in the map
class Tile {
public:
   
int tilesetIndex;
   
int tileId;
   
bool isSolid;
   
   
Tile( int setIdx = 0, int id = 0, bool solid = false )
        :
tilesetIndex( setIdx )
       
, tileId( id )
       
, isSolid( solid )
   
{ }
}
;

// Main application class
class TileMapEditor {
private:
   
sf::RenderWindow window;
   
std::vector < sf::Texture > tilesets;
   
std::vector < std::vector < Tile >> map;
   
sf::Sprite tileSprite;
   
sf::Vector2i selectedTileset;
   
sf::Vector2i mouseTilePos;
   
bool isDrawing = false;
   
int currentTilesetIndex = 0;
   
int currentTileId = 0;
   
   
// Helper to get tile ID based on neighbors (simple corner/edge matching)
   
int getTileIdFromNeighbors( int x, int y ) {
       
int mask = 0;
       
// Check neighbors: top, right, bottom, left
       
if( y > 0 && map[ y - 1 ][ x ].tileId != 0 ) mask |= 1;
       
       
if( x < MAP_WIDTH - 1 && map[ y ][ x + 1 ].tileId != 0 ) mask |= 2;
       
       
if( y < MAP_HEIGHT - 1 && map[ y + 1 ][ x ].tileId != 0 ) mask |= 4;
       
       
if( x > 0 && map[ y ][ x - 1 ].tileId != 0 ) mask |= 8;
       
       
// Return a tile ID based on neighbor pattern (simplified)
        // This is a basic implementation for 4-directional matching
        // In a real app, you'd have a full tileset with 16+ variants
       
switch( mask ) {
       
case 0: return 0; // No neighbors
       
case 1: return 1; // Only top
       
case 2: return 2; // Only right
       
case 4: return 3; // Only bottom
       
case 8: return 4; // Only left
       
case 1 | 2: return 5; // Top + right
       
case 2 | 4: return 6; // Right + bottom
       
case 4 | 8: return 7; // Bottom + left
       
case 8 | 1: return 8; // Left + top
       
case 1 | 2 | 4: return 9; // Top + right + bottom
       
case 2 | 4 | 8: return 10; // Right + bottom + left
       
case 4 | 8 | 1: return 11; // Bottom + left + top
       
case 8 | 1 | 2: return 12; // Left + top + right
       
case 1 | 2 | 4 | 8: return 13; // All neighbors
       
default: return 14; // Default corner/edge tile
       
}
    }
   
public:
   
TileMapEditor()
        :
window( sf::VideoMode( MAP_WIDTH * TILE_SIZE + 200, MAP_HEIGHT * TILE_SIZE ), "Tile Map Editor" )
   
{
       
// Load tilesets (you can replace these with your own tileset images)
       
for( int i = 0; i < MAX_TILESETS; ++i ) {
           
sf::Texture texture;
           
std::string filename = "tileset_" + std::to_string( i ) + ".png";
           
if( !texture.loadFromFile( filename ) ) {
               
std::cerr << "Failed to load tileset: " << filename << std::endl;
               
// Use a placeholder texture if file not found
               
sf::Image placeholder;
               
placeholder.create( TILE_SIZE, TILE_SIZE, sf::Color::Green );
               
texture.loadFromImage( placeholder );
           
}
           
tilesets.push_back( texture );
       
}
       
       
// Initialize map with empty tiles
       
map.resize( MAP_HEIGHT, std::vector < Tile >( MAP_WIDTH, Tile( 0, 0, false ) ) );
       
       
// Set up tile sprite
       
tileSprite.setOrigin( TILE_SIZE / 2.0f, TILE_SIZE / 2.0f );
   
}
   
   
void run() {
       
sf::Clock clock;
       
while( window.isOpen() ) {
           
sf::Event event;
           
while( window.pollEvent( event ) ) {
               
if( event.type == sf::Event::Closed ) {
                   
window.close();
               
}
               
               
if( event.type == sf::Event::MouseButtonPressed ) {
                   
if( event.mouseButton.button == sf::Mouse::Left ) {
                       
isDrawing = true;
                       
sf::Vector2i pos = sf::Mouse::getPosition( window );
                       
mouseTilePos.x = pos.x / TILE_SIZE;
                       
mouseTilePos.y = pos.y / TILE_SIZE;
                       
                       
if( mouseTilePos.x >= 0 && mouseTilePos.x < MAP_WIDTH &&
                       
mouseTilePos.y >= 0 && mouseTilePos.y < MAP_HEIGHT ) {
                           
// Update tile based on neighbors
                           
int newTileId = getTileIdFromNeighbors( mouseTilePos.x, mouseTilePos.y );
                           
map[ mouseTilePos.y ][ mouseTilePos.x ] = Tile( currentTilesetIndex, newTileId, true );
                       
}
                    }
                }
               
               
if( event.type == sf::Event::MouseButtonReleased ) {
                   
if( event.mouseButton.button == sf::Mouse::Left ) {
                       
isDrawing = false;
                   
}
                }
               
               
if( event.type == sf::Event::MouseMoved ) {
                   
if( isDrawing ) {
                       
sf::Vector2i pos = sf::Mouse::getPosition( window );
                       
int x = pos.x / TILE_SIZE;
                       
int y = pos.y / TILE_SIZE;
                       
                       
if( x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT ) {
                           
int newTileId = getTileIdFromNeighbors( x, y );
                           
map[ y ][ x ] = Tile( currentTilesetIndex, newTileId, true );
                       
}
                    }
                }
               
               
// Handle tileset selection via keyboard
               
if( event.type == sf::Event::KeyPressed ) {
                   
if( event.key.code == sf::Keyboard::Num1 ) currentTilesetIndex = 0;
                   
                   
if( event.key.code == sf::Keyboard::Num2 ) currentTilesetIndex = 1;
                   
                   
if( event.key.code == sf::Keyboard::Num3 ) currentTilesetIndex = 2;
                   
                   
if( event.key.code == sf::Keyboard::Num4 ) currentTilesetIndex = 3;
                   
               
}
            }
           
           
// Clear window
           
window.clear( sf::Color::Black );
           
           
// Draw map
           
for( int y = 0; y < MAP_HEIGHT; ++y ) {
               
for( int x = 0; x < MAP_WIDTH; ++x ) {
                   
const Tile & tile = map[ y ][ x ];
                   
if( tile.tileId != 0 ) {
                       
sf::Sprite sprite;
                       
sprite.setTexture( tilesets[ tile.tilesetIndex ] );
                       
sprite.setTextureRect( sf::IntRect(
                        (
tile.tileId %( tilesets[ tile.tilesetIndex ].getSize().x / TILE_SIZE ) ) * TILE_SIZE,
                       
( tile.tileId /( tilesets[ tile.tilesetIndex ].getSize().x / TILE_SIZE ) ) * TILE_SIZE,
                       
TILE_SIZE, TILE_SIZE
                        ) );
                       
sprite.setPosition( x * TILE_SIZE + TILE_SIZE / 2.0f, y * TILE_SIZE + TILE_SIZE / 2.0f );
                       
window.draw( sprite );
                   
}
                }
            }
           
           
// Draw tileset selection UI
           
sf::Font font;
           
if( !font.loadFromFile( "arial.ttf" ) ) {
               
// Fallback font
               
font = sf::Font();
           
}
           
           
sf::Text infoText;
           
infoText.setFont( font );
           
infoText.setCharacterSize( 16 );
           
infoText.setFillColor( sf::Color::White );
           
infoText.setPosition( MAP_WIDTH * TILE_SIZE + 10, 10 );
           
infoText.setString( "Tileset: " + std::to_string( currentTilesetIndex + 1 ) );
           
window.draw( infoText );
           
           
// Draw tileset preview
           
for( int i = 0; i < MAX_TILESETS; ++i ) {
               
sf::Sprite preview;
               
preview.setTexture( tilesets[ i ] );
               
preview.setPosition( MAP_WIDTH * TILE_SIZE + 10, 40 + i * 40 );
               
preview.setScale( 1.0f, 1.0f );
               
window.draw( preview );
               
               
sf::Text label;
               
label.setFont( font );
               
label.setCharacterSize( 12 );
               
label.setFillColor( sf::Color::White );
               
label.setPosition( MAP_WIDTH * TILE_SIZE + 50, 45 + i * 40 );
               
label.setString( "Set " + std::to_string( i + 1 ) );
               
window.draw( label );
           
}
           
           
// Draw cursor
           
sf::CircleShape cursor( 5 );
           
cursor.setFillColor( sf::Color::Red );
           
sf::Vector2i mousePos = sf::Mouse::getPosition( window );
           
cursor.setPosition( mousePos.x - 5, mousePos.y - 5 );
           
window.draw( cursor );
           
           
window.display();
       
}
    }
}
;

int main() {
   
TileMapEditor editor;
   
editor.run();
   
return 0;
}
Nie sprawdzałem czy działa/czy ma sens - mały lokalny model LLM to wygenerował.
P-183467
skovv
» 2025-11-14 19:33:47
no jak no stary, silnik napisałeś a tego nie możesz. Nie poddawaj się :D

C/C++
class Group {
public:
   
std::string Name;
   
GeSprite * main, * left, * right, * up, * down;
};
Group * lista[ 100 ][ 100 ]; // lul

// Przy rysowaniu:
for( int w = 0; w < 100; w++ ) {
   
for( int h = 0; h < 100; h++ ) {
       
auto e = lista[ w ][ h ];
       
if( e != nullptr ) {
           
if( NIE MA MOJEJ GRUPY Z LEWEJ ) RYSUJ TEN LEWY
            else if( NIE MA PO PRAWEJ ) RYSUJ TEN PRAWY
            else if( NIE MA Z GORY ) RYSUJ TEN GORNY
            else if( NIE MA Z DOLU ) RYSUJ TEN DOLNY
            else RYSUJ TEN SRODKOWY
        }
    }
}
   
P-183468
tBane
Temat założony przez niniejszego użytkownika
» 2025-11-14 20:08:48
DejaVu niestety, ale program nie działa :-/ Podzieliłem tileset na cztery tilesety. Poprawiłem wczytywanie czcionki i odpaliłem program. Ale nie da się rysować mapy.
Wrzuciłem ten projekt na Github.
https://github.com/tBane1995/Tiled

Skovv Silnik wbrew pozorom jest prosty do napisania tylko czasochłonny, a algorytm do generowania kafelków jest złożony :-/
P-183469
« 1 » 2 3
  Strona 1 z 3 Następna strona