rafallauterbach Temat założony przez niniejszego użytkownika |
sdl2, wycieki pamięci i valgrind » 2019-01-28 16:35:49 Czy ktoś kiedyś szukał wycieków w programie z SDL za pomocą Valgrind? Prosiłbym o informację czy popełniam jakiś rażący bład. Z tego co rozumiem, to program ten wyłapuje gdy próbuję użyć niewłaściwego pointera, ale w połączeniu z SDL-em (SDL2) wyrzuca mi co chwila błedy typu : ==9578== Invalid write of size 4 (... backtrace ...) ==9578== Address 0x7f2bf6fcb070 is not stack'd, malloc'd or (recently) free'd
Wszędzie gdzie używam "magicznej" funkcji SDLa pointera doo typedefu, które daje mi SDL (konkretnie : typ "SDL_Renderer*") dostaję taki błąd jak powyżej -> funkcje których używam i dostaję błąd tego typu są poniżej... -1- SDL_RenderPresent( Game::gameRenderer );
nie widzę tu mojego błędu, bo używam tylko SDLowych funkcji. -2- SDL_RenderCopy( renderer, text_text, NULL, & renderQuad );
-3- SDL_RenderCopy( gRenderer, mTexture, & clip, & r );
Uznałem, że pominę te błędy, pokasowałem je i wyłonił mi się jeszcze jeden błąd, którego nie rozumiem.. ==9578== Mismatched free() / delete / delete [] ==9578== at 0x4C2F400: operator delete(void*) (vg_replace_malloc.c:576) ==9578== by 0x407500: Object::write(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SDL_Rect, SDL_Renderer*) (Object.cpp:53) ==9578== by 0x4075E8: Object::draw(SDL_Renderer*) (Object.cpp:67) ==9578== by 0x4092F6: Scene::draw_objects() (Scene.cpp:113) ==9578== by 0x408F66: Scene::draw_scene() (Scene.cpp:34) ==9578== by 0x403B6C: Game::loop() (Game.cpp:96) ==9578== by 0x402D4E: main (main.cpp:14) ==9578== Address 0x12c2cd50 is 0 bytes inside a block of size 96 alloc'd ==9578== at 0x4C2FF6C: calloc (vg_replace_malloc.c:752) ==9578== by 0x4EE737F: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.4.0) ==9578== by 0x537467E: TTF_RenderUTF8_Solid (in /usr/lib/x86_64-linux-gnu/libSDL2_ttf-2.0.so.0.14.0) ==9578== by 0x5374A69: TTF_RenderText_Solid (in /usr/lib/x86_64-linux-gnu/libSDL2_ttf-2.0.so.0.14.0) ==9578== by 0x407407: Object::write(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, SDL_Rect, SDL_Renderer*) (Object.cpp:38) ==9578== by 0x4075E8: Object::draw(SDL_Renderer*) (Object.cpp:67) ==9578== by 0x4092F6: Scene::draw_objects() (Scene.cpp:113) ==9578== by 0x408F66: Scene::draw_scene() (Scene.cpp:34) ==9578== by 0x403B6C: Game::loop() (Game.cpp:96) ==9578== by 0x402D4E: main (main.cpp:14) ==9578==
Wrzucę kod, który wydaje mi się istotny. W razie czego podam go więcej oczywiście... void Object::write( std::string caption, SDL_Rect placement, SDL_Renderer * renderer ) { SDL_Color font_color = { 210, 210, 250 }; SDL_Surface * text_surface; if( caption != "" ) { if( !( text_surface = TTF_RenderText_Solid( font, caption.c_str(), font_color ) ) ) { std::cout << "E: Could not create surface from text : " << TTF_GetError << std::endl; } else { SDL_Texture * text_text = SDL_CreateTextureFromSurface( renderer, text_surface ); int text_x =( placement.x + placement.w / 2 ) - text_surface->w / 2; int text_y =( placement.y + placement.h / 2 ) - text_surface->h / 2; SDL_Rect renderQuad = { text_x, text_y, text_surface->w, text_surface->h }; SDL_RenderCopy( renderer, text_text, NULL, & renderQuad ); SDL_DestroyTexture( text_text ); delete text_surface; } } }
Niestety nigdy w życiu nie używałem valgrinda do tej pory i wydaje mi się że problem leży w SDL-u ( albo źle używam SDL_Renderer* (?) ) Przepraszam za chaotyczny post, ale próbuję -nie- napisać posta na 1000 linijek i przeskakuje wątkami w głowie tak, żeby szybko przekazać dużo treści. Odcinając się trochę tematu stricte błedów postanowiłem użyć valgrinda, żeby wytropić wyciek pamięci, którego się dorobiłem pisząc swoją grę. Po odpaleniu mapy wycieka mi ~1%RAMu na 2-3 sekundy ( z 4GB RAM -> 10-20MB/s -> być może 330kb na każdą klatkę (60FPS) ). Najgorsze, że nie wiem kiedy wyciek powstał i w którym miejscu kodu go szukać, bo wykryłem go teraz, ale najprawdopodobniej jest on już jakiś czas (pierwszy raz testowałem grę przez ponad kilka minut i skończył mi się ram, zacząłem korzystać ze swapu i ... i tak dalej). Myślę, że te 330kb/klatkę ładnie pasowałoby do kilku surface-ów stworzonych za pomocą TTF_RenderText_Solid, których np nie udaje mi się zdealokować. Albo cały problem leży w tym że źle używam pointera do SDL_Renderer i o tym nie wiem. Dorzucę więcej kodu kilku klas w razie gdyby ktoś był ciekawy od razu dodam, że fonty potraktowałem mocno po macoszemu i są bardzo tym czasowo zastosowane. Nie mam jeszcze pomysłu jak je ładnie ułożyć/włożyć do jakiejś struktury Object.cpp #include "Object.h" #include "Texture.h" #include "Scene.h"
TTF_Font * Object::font;
Object::Object( Scene * host ) { placement.x = 0; placement.y = 0; texture = nullptr; overlay = nullptr; host->addObject( this ); }
void Object::resetWH() { placement.w = texture->getWidth(); placement.h = texture->getHeight(); }
bool Object::cover( int x, int y ) { if( x > placement.x ) if( x < placement.x + placement.w ) if( y > placement.y ) if( y < placement.y + placement.h ) return true; return false; }
void Object::write( std::string caption, SDL_Rect placement, SDL_Renderer * renderer ) { SDL_Color font_color = { 210, 210, 250 }; SDL_Surface * text_surface; if( caption != "" ) { if( !( text_surface = TTF_RenderText_Solid( font, caption.c_str(), font_color ) ) ) { std::cout << "E: Could not create surface from text : " << TTF_GetError << std::endl; } else { SDL_Texture * text_text = SDL_CreateTextureFromSurface( renderer, text_surface ); int text_x =( placement.x + placement.w / 2 ) - text_surface->w / 2; int text_y =( placement.y + placement.h / 2 ) - text_surface->h / 2; SDL_Rect renderQuad = { text_x, text_y, text_surface->w, text_surface->h }; SDL_RenderCopy( renderer, text_text, NULL, & renderQuad ); SDL_DestroyTexture( text_text ); delete text_surface; } } }
void Object::draw( SDL_Renderer * renderer ) { if( texture != NULL ) texture->render( placement, renderer ); else std::cout << "E: Texture is null! Cannot display object" << std::endl; if( overlay != NULL ) overlay->render( placement, renderer ); write( caption, placement, renderer ); }
Texture.cpp #include "Texture.h"
std::vector < texname *> Texture_bank::tex;
int SDL_SetRenderDrawColor( SDL_Renderer * target, SDL_Color c ) { return SDL_SetRenderDrawColor( target, c.r, c.g, c.b, c.a ); }
unsigned int Texture_bank::add( Texture * t, std::string n ) { if( Texture_bank::get_by_name( n ) != NULL ) std::cout << "W: Texture name duplicate : " << n << std::endl; texname * texx = new texname(); texx->ture = t; texx->name = n; tex.push_back( texx ); return(( tex.size() - 1 ) ); }
Texture * Texture_bank::get_by_name( std::string name ) { if( tex.size() > 0 ) for( unsigned int i = 0; i < tex.size(); i++ ) { if( tex[ i ]->name == name ) return tex[ i ]->ture; } return NULL; }
void Texture_bank::delete_all() { for( texname * t: tex ) t->ture->free(); tex.clear(); }
std::vector < texname *> Texture_bank::get_all() { return tex; }
void Texture_bank::remove_by_pointer( Texture * texture ) { for( unsigned int i = 0; i < tex.size(); i++ ) if( tex[ i ]->ture == texture ) { tex[ i ]->ture->free(); tex.erase( tex.begin() + i ); } }
std::string Texture::resources_path;
Texture::Texture( std::string name ) : mTexture( NULL ) , mWidth( 0 ) , mHeight( 0 ) { Texture_bank::add( this, name ); } Texture::Texture( std::string name, std::string new_path ) : mTexture( NULL ) , mWidth( 0 ) , mHeight( 0 ) { Texture_bank::add( this, name ); declare_path( new_path ); } Texture::~Texture() { Texture_bank::remove_by_pointer( this ); free(); }
void Texture::declare_path( std::string new_path ) { path = new_path; free(); }
bool Texture::reload( SDL_Renderer * gRenderer ) { SDL_Texture * newTexture = NULL; SDL_Surface * loadedSurface = IMG_Load(( resources_path + path ).c_str() ); if( loadedSurface == NULL ) { printf( "Critical Error, Aborting! Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() ); exit( 1 ); } else { newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface ); if( newTexture == NULL ) { printf( "Critical Error, Aborting! Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() ); exit( 1 ); } else { mWidth = loadedSurface->w; mHeight = loadedSurface->h; } SDL_FreeSurface( loadedSurface ); } mTexture = newTexture; return mTexture != NULL; } #include <sstream> void Texture::LOAD_ALL_TEXTURES( SDL_Renderer * gRenderer ) { std::vector < texname *> tex_list; tex_list = Texture_bank::get_all(); std::cout << " -- LOADING TEXTURES -- " << std::endl; for( unsigned int i = 0; i < tex_list.size(); i++ ) { std::stringstream data; unsigned int actual =(( i ) * 100 ) / tex_list.size(); data << "[ "; if( actual < 10 ) data << " "; if( actual < 100 ) data << " "; data << actual << "% ] " << i + 1 << " out of " << tex_list.size() << std::endl; std::cout << data.str(); tex_list[ i ]->ture->reload( gRenderer ); } if( tex_list.size() != 0 ) std::cout << "[ " << 100 << "% ]" << std::endl; std::cout << " -- DONE * " << tex_list.size() << " * TEXTURES LOADED! -- " << std::endl; }
void Texture::free() { if( mTexture != NULL ) { SDL_DestroyTexture( mTexture ); mTexture = NULL; mWidth = 0; mHeight = 0; } } void Texture::render( const SDL_Point p, const SDL_Rect clip, SDL_Renderer * gRenderer ) { SDL_Rect renderQuad = { p.x, p.y, mWidth, mHeight }; render( renderQuad, clip, gRenderer ); } void Texture::render( const SDL_Rect r, const SDL_Rect clip, SDL_Renderer * gRenderer ) { SDL_RenderCopy( gRenderer, mTexture, & clip, & r ); } void Texture::render( const SDL_Point p, SDL_Renderer * gRenderer ) { SDL_Rect renderQuad = { p.x, p.y, mWidth, mHeight }; render( renderQuad, gRenderer ); } void Texture::render( const SDL_Rect r, SDL_Renderer * gRenderer ) { SDL_Rect clip = { 0, 0, mWidth, mHeight }; render( r, clip, gRenderer ); } int Texture::getWidth() { return mWidth; } int Texture::getHeight() { return mHeight; } void Texture::set_texture( SDL_Texture * tex, unsigned int w, unsigned int h ) { mTexture = tex; mWidth = w; mHeight = h; }
SDL_Texture * Texture::get_texture() { return mTexture; }
void Texture::free_all() { Texture_bank::delete_all(); }
Game.cpp #include "Texture.h"
std::vector < texname *> Texture_bank::tex;
int SDL_SetRenderDrawColor( SDL_Renderer * target, SDL_Color c ) { return SDL_SetRenderDrawColor( target, c.r, c.g, c.b, c.a ); }
unsigned int Texture_bank::add( Texture * t, std::string n ) { if( Texture_bank::get_by_name( n ) != NULL ) std::cout << "W: Texture name duplicate : " << n << std::endl; texname * texx = new texname(); texx->ture = t; texx->name = n; tex.push_back( texx ); return(( tex.size() - 1 ) ); }
Texture * Texture_bank::get_by_name( std::string name ) { if( tex.size() > 0 ) for( unsigned int i = 0; i < tex.size(); i++ ) { if( tex[ i ]->name == name ) return tex[ i ]->ture; } return NULL; }
void Texture_bank::delete_all() { for( texname * t: tex ) t->ture->free(); tex.clear(); }
std::vector < texname *> Texture_bank::get_all() { return tex; }
void Texture_bank::remove_by_pointer( Texture * texture ) { for( unsigned int i = 0; i < tex.size(); i++ ) if( tex[ i ]->ture == texture ) { tex[ i ]->ture->free(); tex.erase( tex.begin() + i ); } }
std::string Texture::resources_path;
Texture::Texture( std::string name ) : mTexture( NULL ) , mWidth( 0 ) , mHeight( 0 ) { Texture_bank::add( this, name ); } Texture::Texture( std::string name, std::string new_path ) : mTexture( NULL ) , mWidth( 0 ) , mHeight( 0 ) { Texture_bank::add( this, name ); declare_path( new_path ); } Texture::~Texture() { Texture_bank::remove_by_pointer( this ); free(); }
void Texture::declare_path( std::string new_path ) { path = new_path; free(); }
bool Texture::reload( SDL_Renderer * gRenderer ) { SDL_Texture * newTexture = NULL; SDL_Surface * loadedSurface = IMG_Load(( resources_path + path ).c_str() ); if( loadedSurface == NULL ) { printf( "Critical Error, Aborting! Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() ); exit( 1 ); } else { newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface ); if( newTexture == NULL ) { printf( "Critical Error, Aborting! Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() ); exit( 1 ); } else { mWidth = loadedSurface->w; mHeight = loadedSurface->h; } SDL_FreeSurface( loadedSurface ); } mTexture = newTexture; return mTexture != NULL; } #include <sstream> void Texture::LOAD_ALL_TEXTURES( SDL_Renderer * gRenderer ) { std::vector < texname *> tex_list; tex_list = Texture_bank::get_all(); std::cout << " -- LOADING TEXTURES -- " << std::endl; for( unsigned int i = 0; i < tex_list.size(); i++ ) { std::stringstream data; unsigned int actual =(( i ) * 100 ) / tex_list.size(); data << "[ "; if( actual < 10 ) data << " "; if( actual < 100 ) data << " "; data << actual << "% ] " << i + 1 << " out of " << tex_list.size() << std::endl; std::cout << data.str(); tex_list[ i ]->ture->reload( gRenderer ); } if( tex_list.size() != 0 ) std::cout << "[ " << 100 << "% ]" << std::endl; std::cout << " -- DONE * " << tex_list.size() << " * TEXTURES LOADED! -- " << std::endl; }
void Texture::free() { if( mTexture != NULL ) { SDL_DestroyTexture( mTexture ); mTexture = NULL; mWidth = 0; mHeight = 0; } } void Texture::render( const SDL_Point p, const SDL_Rect clip, SDL_Renderer * gRenderer ) { SDL_Rect renderQuad = { p.x, p.y, mWidth, mHeight }; render( renderQuad, clip, gRenderer ); } void Texture::render( const SDL_Rect r, const SDL_Rect clip, SDL_Renderer * gRenderer ) { SDL_RenderCopy( gRenderer, mTexture, & clip, & r ); } void Texture::render( const SDL_Point p, SDL_Renderer * gRenderer ) { SDL_Rect renderQuad = { p.x, p.y, mWidth, mHeight }; render( renderQuad, gRenderer ); } void Texture::render( const SDL_Rect r, SDL_Renderer * gRenderer ) { SDL_Rect clip = { 0, 0, mWidth, mHeight }; render( r, clip, gRenderer ); } int Texture::getWidth() { return mWidth; } int Texture::getHeight() { return mHeight; } void Texture::set_texture( SDL_Texture * tex, unsigned int w, unsigned int h ) { mTexture = tex; mWidth = w; mHeight = h; }
SDL_Texture * Texture::get_texture() { return mTexture; }
void Texture::free_all() { Texture_bank::delete_all(); }
A poniżej istny festiwal tymczasowych rozwiązań, które później planuję zastąpić jakimś wczytywaniem danych z plików. map.cpp #include "Map.h"
#include "Tile.h" #include "Texture.h" #include "Player.h" #include <cstdint>
class Scene;
#define TILESIZE 48
enum players { PNULL, Porange, Ppurple, Pblue, Pred, P_MAX };
SDL_Color Pcols[ P_MAX ];
Player * Pzero = new Player(); Player * P1 = new Player(); Player * P2 = new Player(); Player * P3 = new Player(); Player * P4 = new Player();
Map::Map( Scene * parent, unsigned int height, unsigned int width ) : Button( parent ) { height = 11; width = 11; int table[ 121 ] = { 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 0, 3, 1, 1, 3, 3, 0, 0, 0, 2, 2, 1, 3, 3, 2, 3, 1, 0, 2, 2, 2, 2, 1, 1, 3, 3, 3, 1, 1, 2, 2, 2, 2, 0, 1, 3, 2, 3, 3, 1, 2, 2, 0, 0, 0, 3, 3, 1, 1, 3, 0, 0, 0, 0, 0, 4, 0, 1, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, }; map_width = 11; SDL_Point localization; for( localization.y = 0; localization.y < height; localization.y++ ) { for( localization.x = 0; localization.x < width; localization.x++ ) { Tile * t; int type = table[( localization.y * map_width ) + localization.x ]; if( type < 4 ) t = new Tile(( Tile::types ) type, localization ); if( type == 4 ) { t = new Tile( Tile::grassland, localization ); t->build_city(); } t->set_owner( Pzero ); t->have_unit = false; unsigned int h = localization.y; unsigned int w = localization.x; if( w > 0 && w < 4 && h > 0 && h < 4 ) { t->set_owner( P1 ); } if( w > 0 && w < 4 && h > 6 && h < 10 ) { t->set_owner( P2 ); } if( w > 6 && w < 10 && h > 0 && h < 4 ) { t->set_owner( P3 ); } if( w > 6 && w < 10 && h > 6 && h < 10 ) { t->set_owner( P4 ); } teritories.push_back( t ); } } Object * O_temp; O_temp = new Object( parent ); O_temp->set_placement(( SDL_Rect ) {.x = 580,.y = 120,.w = 200,.h = 60 } ); O_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); P1->money_print = O_temp; O_temp = new Object( parent ); O_temp->set_placement(( SDL_Rect ) {.x = 580,.y = 220,.w = 200,.h = 60 } ); O_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); P2->money_print = O_temp; O_temp = new Object( parent ); O_temp->set_placement(( SDL_Rect ) {.x = 580,.y = 320,.w = 200,.h = 60 } ); O_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); P3->money_print = O_temp; O_temp = new Object( parent ); O_temp->set_placement(( SDL_Rect ) {.x = 580,.y = 420,.w = 200,.h = 60 } ); O_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); P4->money_print = O_temp; class EoT_Button : public Button { public: EoT_Button( Scene * s, Map * o_map ) : Button( s ) { owner_map = o_map; } private: void onClick( const SDL_Event & event ) { owner_map->EoT(); } Map * owner_map; }; O_temp = new EoT_Button( parent, this ); O_temp->set_placement(( SDL_Rect ) {.x = 580,.y = 520,.w = 200,.h = 60 } ); O_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); O_temp->set_caption( "End of Turn" ); P1->get_money( 10000 ); P2->get_money( 100 ); P3->get_money( 100 ); P4->get_money( 100 ); cam.x = - 10; cam.y = - 10; }
#define CASH_PER_CITY_LVL 100
void Map::EoT() { for( Tile * teritory: teritories ) { teritory->unit_move = true; teritory->get_owner()->get_money( teritory->get_city_lvl() * CASH_PER_CITY_LVL ); Tile::selected = nullptr; } }
void Map::draw( SDL_Renderer * renderer ) { Object::draw( renderer ); #define FRAME_LAST 24 if( draw_frame_counter < FRAME_LAST ) draw_frame_counter++; else draw_frame_counter = 0; const int FIRST_TILE_X = cam.x / TILESIZE - 1; const int LAST_TILE_X =( cam.x + placement.h ) / TILESIZE + 1; const int FIRST_TILE_Y = cam.y / TILESIZE - 1; const int LAST_TILE_Y =( cam.y + placement.w ) / TILESIZE + 1; for( int tile_y = FIRST_TILE_Y; tile_y < LAST_TILE_Y; tile_y++ ) { for( int tile_x = FIRST_TILE_X; tile_x < LAST_TILE_X; tile_x++ ) { Texture * tex; Tile * terr = get_territory( tile_y, tile_x ); if( terr != NULL ) switch( terr->get_type() ) { case Tile::grassland: tex = Texture_bank::get_by_name( "m_grassland" ); break; case Tile::ocean: tex = Texture_bank::get_by_name( "m_ocean" ); break; case Tile::desert: tex = Texture_bank::get_by_name( "m_desert" ); break; case Tile::hills: tex = Texture_bank::get_by_name( "m_hills" ); break; default: tex = Texture_bank::get_by_name( "m_grassland" ); } else tex = Texture_bank::get_by_name( "m_ambient" ); SDL_Rect rend_place; rend_place.w = TILESIZE; rend_place.h = TILESIZE; rend_place.x = tile_x * TILESIZE + placement.x - cam.x; rend_place.y = tile_y * TILESIZE + placement.y - cam.y; if( rend_place.x < placement.x ) { rend_place.w -= placement.x - rend_place.x; rend_place.x = placement.x; } if( rend_place.y < placement.y ) { rend_place.h -= placement.y - rend_place.y; rend_place.y = placement.y; } int max_x = placement.x + placement.w - TILESIZE, max_y = placement.y + placement.h - TILESIZE; if( rend_place.x > max_x ) { rend_place.w -= rend_place.x - max_x; rend_place.x = max_x + TILESIZE - rend_place.w; } if( rend_place.y > max_y ) { rend_place.h -= rend_place.y - max_y; rend_place.y = max_y + TILESIZE - rend_place.h; } tex->render( rend_place, renderer ); if( terr != NULL ) { SDL_Color col = terr->get_owner()->get_color(); col.a *= 0.25; SDL_SetRenderDrawColor( renderer, col ); SDL_RenderFillRect( renderer, & rend_place ); if( terr->get_city_lvl() ) { tex = Texture_bank::get_by_name( "m_city" ); if( terr == Tile::selected ) { if( draw_frame_counter > FRAME_LAST / 4 ) tex->render( rend_place, renderer ); } else tex->render( rend_place, renderer ); if( terr->get_city_lvl() > 1 ) { std::string a = std::to_string( terr->get_city_lvl() ); Object::write( a, rend_place, renderer ); } } SDL_RenderFillRect( renderer, & rend_place ); if( terr->have_unit ) { tex = Texture_bank::get_by_name( "m_soldier" ); if( terr == Tile::selected && terr->unit_move ) { if( draw_frame_counter > FRAME_LAST / 4 ) tex->render( rend_place, renderer ); } else tex->render( rend_place, renderer ); } if( terr == Tile::selected ) { tex = Texture_bank::get_by_name( "m_selection" ); tex->render( rend_place, renderer ); } } } } }
Tile * Map::get_territory( unsigned int y, unsigned int x ) { unsigned int tNR = y * map_width + x; if( x >= map_width ) return NULL; if( tNR < teritories.size() ) return teritories[ tNR ]; else return NULL; } void Map::onClick( const SDL_Event & event ) { }
bool Map::fight( Tile * attacker, Tile * defender ) { int power_attack = 6; int power_defend = 6; if( defender->get_type() == Tile::desert ) power_defend -= 2; if( defender->get_type() == Tile::hills ) power_defend += 3; power_defend += defender->get_city_lvl(); int attack_roll = Game::get_random( power_attack ); int defend_roll = Game::get_random( power_defend ); if( attack_roll > 4 ) defender->raze_city(); if( attack_roll > defend_roll ) return true; else { if( attack_roll == defend_roll ) defender->have_unit = false; attacker->have_unit = false; return false; } }
bool Map::try_move( Tile * start, Tile * finish ) { if( start == finish ) return false; if( start == nullptr or finish == nullptr ) return false; if( finish->get_type() == Tile::ocean ) return false; if( start->have_unit == false ) return false; if( start->unit_move == false ) return false; if( abs( finish->get_x() - start->get_x() ) > 1 or abs( finish->get_y() - start->get_y() ) > 1 ) return false; if( finish->have_unit ) { if( finish->get_owner() == start->get_owner() ) { return false; } else return fight( start, finish ); } return true; }
void Map::onMouseUp( const SDL_Event & event ) { SDL_Point select; unsigned int x = event.button.x; unsigned int y = event.button.y; select.x =( x - placement.x + cam.x ) / TILESIZE; select.y =( y - placement.y + cam.y ) / TILESIZE; Tile * new_selected = get_territory( select.y, select.x ); if( event.button.button == SDL_BUTTON_LEFT ) { if( Tile::selected != NULL ) if( Tile::selected->get_owner() == P1 ) { if( Tile::selected == new_selected ) { if( Tile::selected->have_unit == true ) { ; } else { if( P1->pay( Pzero, 1000 ) ) new_selected->have_unit = true; new_selected->unit_move = true; new_selected = NULL; } } if( try_move( Tile::selected, new_selected ) ) { Tile::selected->have_unit = false; new_selected->have_unit = true; new_selected->unit_move = false; new_selected->set_owner( P1 ); new_selected = NULL; } } Tile::selected = new_selected; } if( event.button.button == SDL_BUTTON_RIGHT ) { if( Tile::selected != NULL ) if( Tile::selected->get_owner() == P1 ) { if( Tile::selected == new_selected ) { if( Tile::selected->get_city_lvl() > 0 ) { if( P1->pay( Pzero, 3000 +( 1000 * new_selected->get_city_lvl() ) ) ) new_selected->build_city(); new_selected = NULL; } else { if( P1->pay( Pzero, 3000 ) ) new_selected->build_city(); new_selected = NULL; } } } } }
Scene_loader.cpp #include "Scenes/Scene_loader.h" #include "Scene.h" #include "Texture.h" #include "Game.h" #include "Button.h" #include "Map.h"
Scene * Scene_loader::Main_menu; Scene * Scene_loader::New_Game_scene; Scene * Scene_loader::Game_scene; Scene * Scene_loader::Settings;
void Scene_loader::init_scenes() { Object * O_temp; Button * B_temp; new Texture( "scene main - background", "main menu/main scene.png" ); new Texture( "scene game - background", "main menu/game scene.png" ); new Texture( "game - background", "main menu/game back.png" ); new Texture( "button base", "main menu/menu button.png" ); new Texture( "map canvas - empty", "main menu/canvas.png" ); new Texture( "m_selection", "game/Select.png" ); new Texture( "m_ambient", "game/Ambient.png" ); new Texture( "m_grassland", "game/Grassland.jpg" ); new Texture( "m_desert", "game/Desert.jpg" ); new Texture( "m_ocean", "game/Ocean.jpg" ); new Texture( "m_hills", "game/Hills.jpg" ); new Texture( "m_city", "game/city.png" ); new Texture( "m_soldier", "game/assian_soldier.png" ); new Texture( "Ppurple mark", "game/Purple.png" ); new Texture( "Porange mark", "game/Orange.png" ); new Texture( "Pblue mark", "game/Blue.png" ); new Texture( "Pred mark", "game/Red.png" ); class GScene : public Scene { public: GScene() { GMap = new Map( this, 5, 6 ); GMap->set_placement(( SDL_Rect ) {.x = 12,.y = 12,.w = 548,.h = 548 } ); GMap->set_texture( Texture_bank::get_by_name( "map canvas - empty" ) ); } private: void get_KEY() { const Uint8 * keyboardState = SDL_GetKeyboardState( NULL ); #define CAMERA_SPEED 4 if( keyboardState[ SDL_SCANCODE_DOWN ] ) GMap->camera_mv( CAMERA_SPEED, 0 ); if( keyboardState[ SDL_SCANCODE_UP ] ) GMap->camera_mv( - CAMERA_SPEED, 0 ); if( keyboardState[ SDL_SCANCODE_RIGHT ] ) GMap->camera_mv( 0, CAMERA_SPEED ); if( keyboardState[ SDL_SCANCODE_LEFT ] ) GMap->camera_mv( 0, - CAMERA_SPEED ); if( keyboardState[ SDL_SCANCODE_ESCAPE ] ) Scene::load( Main_menu ); } Map * GMap; }; Main_menu = new Scene(); New_Game_scene = new Scene(); Game_scene = new GScene(); Settings = new Scene(); Main_menu->setBackground( Texture_bank::get_by_name( "scene main - background" ) ); Game::scenes.push_back( Main_menu ); class New_Game_Button : public Button { public: New_Game_Button( Scene * s ) : Button( s ) { } private: void onClick( const SDL_Event & event ) { Scene::load( New_Game_scene ); } }; B_temp = new New_Game_Button( Main_menu ); B_temp->set_placement(( SDL_Rect ) {.x = 140,.y = 60,.w = 500,.h = 80 } ); B_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); B_temp->set_caption( "New Game" ); class Quit_Button : public Button { public: Quit_Button( Scene * s ) : Button( s ) { } private: void onClick( const SDL_Event & event ) { Game::exit(); } }; B_temp = new Quit_Button( Main_menu ); B_temp->set_placement(( SDL_Rect ) {.x = 140,.y = 460,.w = 500,.h = 80 } ); B_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); B_temp->set_caption( "Exit" ); New_Game_scene->setBackground( Texture_bank::get_by_name( "scene game - background" ) ); Game::scenes.push_back( New_Game_scene ); class Start_Game_Button : public Button { public: Start_Game_Button( Scene * s ) : Button( s ) { } private: void onClick( const SDL_Event & event ) { Scene::load( Game_scene ); } }; B_temp = new Start_Game_Button( New_Game_scene ); B_temp->set_placement(( SDL_Rect ) {.x = 140,.y = 60,.w = 500,.h = 80 } ); B_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); B_temp->set_caption( "WTF button" ); class Load_Main_Menu : public Button { public: Load_Main_Menu( Scene * s ) : Button( s ) { } private: void onClick( const SDL_Event & event ) { Scene::load( Main_menu ); } }; B_temp = new Load_Main_Menu( New_Game_scene ); B_temp->set_placement(( SDL_Rect ) {.x = 140,.y = 460,.w = 500,.h = 80 } ); B_temp->set_texture( Texture_bank::get_by_name( "button base" ) ); B_temp->set_caption( "Back" ); Game_scene->setBackground( Texture_bank::get_by_name( "game - background" ) ); Game::scenes.push_back( Game_scene ); }
|