Forum - C/C++
- Istanziare Oggetti Dinamicamente
RiccardoG97 (Member )
Pro
Messaggi: 133
Iscritto: 03/01/2012
Ciao a tutti ragazzi.
Vi mostro il codice del mio programma: (Ci sono 3 files: Ball.h, Ball.cpp e Main.cpp)
:.Ball.h.:
Codice sorgente - presumibilmente C++
//Ball.h
#include "SDL.h"
class Ball
{
public :
Ball ( void ) ;
~Ball ( void ) ;
void makeBall ( SDL_Surface * ) ;
void moveBall ( void ) ;
void ballBounce ( void ) ;
private :
SDL_Surface * ball;
SDL_Rect ballRect;
enum ballDirections { TOPLEFT = 1, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT } ;
ballDirections Directions;
static const int speed;
int direction;
} ;
:.Ball.cpp.:
Codice sorgente - presumibilmente C++
//Ball.cpp
#include "Ball.h"
#include "SDL.h"
#include <ctime>
Ball:: Ball ( void )
{
ball = SDL_LoadBMP ( "Ball.bmp" ) ;
ballRect.x = 300 ;
ballRect.y = 300 ;
direction = 1 + rand ( ) % 4 ;
if ( direction == 1 )
Directions = TOPLEFT;
else if ( direction == 2 )
Directions = TOPRIGHT;
else if ( direction == 3 )
Directions = BOTTOMLEFT;
else
Directions = BOTTOMRIGHT;
}
Ball:: ~Ball ( void )
{
SDL_FreeSurface ( ball ) ;
}
void Ball:: makeBall ( SDL_Surface * screen )
{
SDL_BlitSurface ( ball, NULL , screen, & ballRect ) ;
}
void Ball:: moveBall ( void )
{
if ( Directions == TOPLEFT )
{
ballRect.x - = speed;
ballRect.y - = speed;
}
else if ( Directions == TOPRIGHT )
{
ballRect.x + = speed;
ballRect.y - = speed;
}
else if ( Directions == BOTTOMLEFT )
{
ballRect.x - = speed;
ballRect.y + = speed;
}
else
{
ballRect.x + = speed;
ballRect.y + = speed;
}
}
void Ball:: ballBounce ( void )
{
if ( ballRect.x <= 0 )
{
if ( Directions == TOPLEFT )
Directions = TOPRIGHT;
else
Directions = BOTTOMRIGHT;
}
else if ( ballRect.x >= 600 )
{
if ( Directions == TOPRIGHT )
Directions = TOPLEFT;
else
Directions = BOTTOMLEFT;
}
else if ( ballRect.y <= 0 )
{
if ( Directions == TOPLEFT )
Directions = BOTTOMLEFT;
else
Directions = BOTTOMRIGHT;
}
else if ( ballRect.y >= 500 )
{
if ( Directions == BOTTOMLEFT )
Directions = TOPLEFT;
else
Directions = TOPRIGHT;
}
}
:.Main.cpp.:
Codice sorgente - presumibilmente C++
//Main.cpp
#include "SDL.h"
#include <iostream>
#include "Ball.h"
#include <vector>
using namespace std;
//Surfaces
SDL_Surface * screen = NULL ;
SDL_Surface * background = NULL ;
SDL_Event evento, testEvento;
Uint8 * keys;
//Variabili
const int xDialog = 600 ;
const int yDialog = 500 ;
const int bpp = 32 ;
const int frameSkip = 10 ;
int objects = 0 ;
int newobj = 0 ;
//Funzioni
void makeBackground ( void ) ;
void freeSurfaces ( void ) ;
//Definizione delle funzioni
void makeBackground ( void )
{
SDL_BlitSurface ( background, NULL , screen, NULL ) ;
}
void freeSurfaces ( void )
{
SDL_FreeSurface ( background ) ;
}
int main ( int argc, char * argv[ ] )
{
if ( SDL_Init ( SDL_INIT_EVERYTHING ) ! = 0 )
return 1 ;
screen = SDL_SetVideoMode ( xDialog, yDialog, bpp, NULL ) ;
if ( screen == NULL )
return - 1 ;
SDL_WM_SetCaption ( "Instanziare Dinamicamente Oggetti" , NULL ) ;
//Dichiarazione del vettore oggetti
vector< Ball> oggetti;
Ball palla;
oggetti.push_back ( palla ) ; //FINO A QUA FUNZIONA, INFATTI SULLO SCHERMO APPARE UNA PALLA CHE SI MUOVE E RIMBALZA
objects = 1 ;
//Carica le immagini
background = SDL_LoadBMP ( "Background.bmp" ) ;
SDL_LockSurface ( screen ) ;
while ( true )
{
SDL_Delay ( frameSkip ) ;
if ( newobj < 100 )
newobj + = 10 ;
if ( SDL_PushEvent ( & testEvento ) == 0 )
{
SDL_PollEvent ( & evento ) ;
keys = SDL_GetKeyState ( NULL ) ;
if ( ( keys[ SDLK_SPACE] == SDL_PRESSED ) && newobj == 100 )
{
objects++ ;
oggetti.push_back ( Ball( ) ) ; //IL PROBLEMA PENSO SIA QUA... INFATTI QUANDO PREMO SPACE VADO INCONTRO AD UN ERRORE FATALE
newobj = 0 ;
}
if ( evento.type == SDL_QUIT )
{
freeSurfaces( ) ;
SDL_Quit( ) ;
}
}
SDL_UnlockSurface ( screen ) ;
makeBackground( ) ;
for ( int i = 0 ; i < oggetti.size ( ) ; i++ )
{
oggetti[ i] .makeBall ( screen ) ;
oggetti[ i] .moveBall ( ) ;
oggetti[ i] .ballBounce ( ) ;
}
SDL_LockSurface ( screen ) ;
SDL_Flip ( screen ) ;
}
freeSurfaces( ) ;
SDL_Quit( ) ;
}
Per me non c'è bisogno di guardare tutto il codice, ma semplicemente penso di avere problemi nella riga:
Codice sorgente - presumibilmente Plain Text
oggetti.push_back ( Ball() );
Non ho errori di sintassi, ma un errore fatale durante l'esecuzione..
Grazie a tutti quelli che mi risponderanno
Ultima modifica effettuata da RiccardoG97 il 09/04/2012 alle 10:04
andrex91 (Member )
Pro
Messaggi: 101
Iscritto: 01/05/2009
Quando inserisci un elemento nel vector, questo viene copiato ( quindi il puntatore a SDL_Surface punta alla stessa risorsa dell'originale ).
Di conseguenza quando il distruttore dell'oggetto originale chiama la SDL_FreeSurface, ti ritroverai il puntatore a surface della tua copia corrotto.
Potresti fare in modo che le varie istanze dei tuoi oggetti puntino ad un unica risorsa caricata inizialmente ( stai caricando la stessa immagine in memoria per ogni istanza ) che viene rilasciata a fine applicazione e non nel distruttore
RiccardoG97 (Member )
Pro
Messaggi: 133
Iscritto: 03/01/2012
Io vorrei fare un programma che ogni volta che si clicca SPACE si istanzia un nuovo oggetto della classe Ball. Sullo schermo compara una nuova palla che si muove e rimbalza. E' da un sacco di tempo che sto provando a farlo e non ci salto fuori.. potresti spiegarmi ancora che non ho ben capito? Grazie e scusa per la mia ignoranza
andrex91 (Member )
Pro
Messaggi: 101
Iscritto: 01/05/2009
Quello mi sembra che lo faccia già il tuo programma.
L'unico difetto è appunto la chiamata SDL_FreeSurface nel distruttore.
Infatti nel main hai:
Codice sorgente - presumibilmente Plain Text
oggetti.push_back ( Ball() )
Questa chiamata ti crea un oggetto, ( per cui viene caricata l'immagine in memoria ), inserisce una copia di questo oggetto nel vector, e ti distrugge l'oggetto originale ( quello ritornato da Ball(), chiamando SDL_FreeSurface sulla risorsa che serve però ancora alla copia nel vector).
Per ora potresti fare così:
- levi dal costruttore e dal distruttore le due chiamate di caricamento e liberamento della surface.
- potresti aggiungere un parametro al costruttore:
Codice sorgente - presumibilmente Plain Text
Ball::Ball( SDL_Surface* sur ):ball( sur ){...}
- nel main ( oppure ti crei un gestore di risorse ) ti dichiari un puntatore a SDL_Surface( es mySurface )per l'immagine della tua palla e la carichi una sola volta prima del game loop.
- ogni volta che devi inserire una nuova palla:
Codice sorgente - presumibilmente Plain Text
oggetti.push_back( Ball( mySurface ) );
- prima di uscire dall'applicazione chiami una sola volta:
Codice sorgente - presumibilmente Plain Text
SDL_FreeSurface( mySurface );
In questo modo se vuoi avere delle palle con surface diverse, basta che passi loro un puntatore ad un' altra surface
Ultima modifica effettuata da andrex91 il 09/04/2012 alle 12:18
RiccardoG97 (Member )
Pro
Messaggi: 133
Iscritto: 03/01/2012
Grazie 1000, ho capito e ci sono riuscito!! Grazieee
Posto il codice funzionante, per quelli che in futuro avranno il mio stesso problema:
<Ball.h>
Codice sorgente - presumibilmente C++
//Ball.h
#include "SDL.h"
class Ball
{
public :
Ball ( SDL_Surface * ) ;
~Ball ( void ) ;
void makeBall ( SDL_Surface * ) ;
void moveBall ( void ) ;
void ballBounce ( void ) ;
private :
SDL_Surface * myBall;
SDL_Rect ballRect;
enum ballDirections { TOPLEFT = 1, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT } ;
ballDirections Directions;
static const int speed = 2 ;
int direction;
} ;
<Ball.cpp>
Codice sorgente - presumibilmente C++
//Ball.cpp
#include "Ball.h"
#include "SDL.h"
#include <ctime>
Ball:: Ball ( SDL_Surface * ball )
{
myBall = ball;
ballRect.x = 300 ;
ballRect.y = 300 ;
direction = 1 + rand ( ) % 4 ;
if ( direction == 1 )
Directions = TOPLEFT;
else if ( direction == 2 )
Directions = TOPRIGHT;
else if ( direction == 3 )
Directions = BOTTOMLEFT;
else
Directions = BOTTOMRIGHT;
}
Ball:: ~Ball ( void )
{
}
void Ball:: makeBall ( SDL_Surface * screen )
{
SDL_BlitSurface ( myBall, NULL , screen, & ballRect ) ;
}
void Ball:: moveBall ( void )
{
if ( Directions == TOPLEFT )
{
ballRect.x - = speed;
ballRect.y - = speed;
}
else if ( Directions == TOPRIGHT )
{
ballRect.x + = speed;
ballRect.y - = speed;
}
else if ( Directions == BOTTOMLEFT )
{
ballRect.x - = speed;
ballRect.y + = speed;
}
else
{
ballRect.x + = speed;
ballRect.y + = speed;
}
}
void Ball:: ballBounce ( void )
{
if ( ballRect.x <= 0 )
{
if ( Directions == TOPLEFT )
Directions = TOPRIGHT;
else
Directions = BOTTOMRIGHT;
}
else if ( ballRect.x >= 600 )
{
if ( Directions == TOPRIGHT )
Directions = TOPLEFT;
else
Directions = BOTTOMLEFT;
}
else if ( ballRect.y <= 0 )
{
if ( Directions == TOPLEFT )
Directions = BOTTOMLEFT;
else
Directions = BOTTOMRIGHT;
}
else if ( ballRect.y >= 500 )
{
if ( Directions == BOTTOMLEFT )
Directions = TOPLEFT;
else
Directions = TOPRIGHT;
}
}
<Main.cpp>
Codice sorgente - presumibilmente C++
//Main.cpp
#include "SDL.h"
#include <iostream>
#include "Ball.h"
#include <vector>
using namespace std;
//Surfaces
SDL_Surface * screen = NULL ;
SDL_Surface * background = NULL ;
SDL_Surface * ball = NULL ;
SDL_Event evento, testEvento;
Uint8 * keys;
//Variabili
const int xDialog = 600 ;
const int yDialog = 500 ;
const int bpp = 32 ;
const int frameSkip = 10 ;
int objects = 0 ;
int newobj = 0 ;
int direction;
int speed;
//Funzioni
void makeBackground ( void ) ;
void freeSurfaces ( void ) ;
//Definizione delle funzioni
void makeBackground ( void )
{
SDL_BlitSurface ( background, NULL , screen, NULL ) ;
}
void freeSurfaces ( void )
{
SDL_FreeSurface ( background ) ;
SDL_FreeSurface ( ball ) ;
}
int main ( int argc, char * argv[ ] )
{
if ( SDL_Init ( SDL_INIT_EVERYTHING ) ! = 0 )
return 1 ;
screen = SDL_SetVideoMode ( xDialog, yDialog, bpp, NULL ) ;
if ( screen == NULL )
return - 1 ;
SDL_WM_SetCaption ( "Instanziare Dinamicamente Oggetti" , NULL ) ;
//Dichiarazione del vettore oggetti
vector< Ball> oggetti;
/*
Ball palla;
oggetti.push_back ( palla ); //FINO A QUA FUNZIONA, INFATTI SULLO SCHERMO APPARE UNA PALLA CHE SI MUOVE E RIMBALZA
*/
//Carica le immagini
background = SDL_LoadBMP ( "Background.bmp" ) ;
ball = SDL_LoadBMP ( "Ball.bmp" ) ;
SDL_LockSurface ( screen ) ;
while ( true )
{
SDL_Delay ( frameSkip ) ;
if ( newobj < 100 )
newobj + = 10 ;
if ( SDL_PushEvent ( & testEvento ) == 0 )
{
SDL_PollEvent ( & evento ) ;
keys = SDL_GetKeyState ( NULL ) ;
if ( ( keys[ SDLK_SPACE] == SDL_PRESSED ) && newobj == 100 )
{
oggetti.push_back ( Ball( ball) ) ; //IL PROBLEMA PENSO SIA QUA... INFATTI QUANDO PREMO SPACE VADO INCONTRO AD UN ERRORE FATALE
newobj = 0 ;
}
if ( evento.type == SDL_QUIT )
{
freeSurfaces( ) ;
SDL_Quit( ) ;
}
}
SDL_UnlockSurface ( screen ) ;
makeBackground( ) ;
for ( int i = 0 ; i < oggetti.size ( ) ; i++ )
{
oggetti[ i] .makeBall ( screen ) ;
oggetti[ i] .moveBall ( ) ;
oggetti[ i] .ballBounce ( ) ;
}
SDL_LockSurface ( screen ) ;
SDL_Flip ( screen ) ;
}
freeSurfaces( ) ;
SDL_Quit( ) ;
}
Se ci sono riuscito devo però ringraziare andrex91! Grazie!