Sign in to follow this  
Fayte

Passing a value into a bound class.

Recommended Posts

Fayte    139
Ok here's the deal,

I have an Image class with a draw function like this:
[CODE]
void Img::Draw(SDL_Surface* surface) {
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}
[/CODE]

I would like to be able to do this in the script:
[CODE]
Image img;

img.x = 0;
img.y = 0;

img.Draw();
[/CODE]

But I need to pass the screen Surface to the draw function I don't want my scripters to have to do img.Draw(GetSurface()); I would like this to be handled through the C++ backend code is there a way that everytime img.Draw() is called in script I can pass the SDL_Surface into the C++ method?

If you need this explained better ask away its 12 A.M. here [img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img] might not have explained it the best. Edited by Fayte

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='saejox' timestamp='1348915413' post='4985001']
how about you also have this draw function

[CODE]
void Img::Draw() {
Draw(GetSurface());
}
[/CODE]
[/quote]

Well I thought that at first too, but the thing is GetSurface(); is in my engine class which has an instance that would need to be passed but I don't know if I can pass the instance into the Image class every time a new one is created in Angelscript. Sorry rather new to Angelscript [img]http://public.gamedev.net//public/style_emoticons/default/sad.png[/img]

Share this post


Link to post
Share on other sites
saejox    714
first divide your problem to small problems.

can you do this in your script now?

[CODE]
Image img;
img.x = 0;
img.y = 0;
[/CODE]

if not please read this section of the manual
[url="http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_api_topic.html"]http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_api_topic.html[/url] Edited by saejox

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='saejox' timestamp='1348925403' post='4985038']
first divide your problem to small problems.

can you do this in your script now?

[CODE]
Image img;
img.x = 0;
img.y = 0;
[/CODE]

if not please read this section of the manual
[url="http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_api_topic.html"]http://www.angelcode..._api_topic.html[/url]
[/quote]
Yesir :) got that far.

Share this post


Link to post
Share on other sites
saejox    714
then i just dont understand why you cant create a second function in you Img class.

class Img
{
void Img::Draw(SDL_Surface* surface)
{
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}

void Img::Draw()
{
Draw(GetSurface());
}
}

register Img::Draw() to script.
like this
[CODE]
r = engine->RegisterObjectMethod("Image", "void Draw()", asMETHODPR(Image, Draw, (void), void), asCALL_THISCALL);
[/CODE]

surely you have access to GetSurface() function in C++. ( or engine->GetSurface() )

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='saejox' timestamp='1348927925' post='4985053']
then i just dont understand why you cant create a second function in you Img class.

class Img
{
void Img::Draw(SDL_Surface* surface)
{
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}

void Img::Draw()
{
Draw(GetSurface());
}
}

register Img::Draw() to script.
like this
[CODE]
r = engine->RegisterObjectMethod("Image", "void Draw()", asMETHODPR(Image, Draw, (void), void), asCALL_THISCALL);
[/CODE]

surely you have access to GetSurface() function in C++. ( or engine->GetSurface() )
[/quote]
You are quite right but I cant pass my engine variable into a c++ class that's not instanced yet can I? Sorry for being newbish like I said I'm new to angelscript. But I don't know how to pass in GetSurface() into my Img class. Without first saying Image img = new Image(engine); on my C++ side.

Share this post


Link to post
Share on other sites
TechRogue    722
Here's how I give my classes access to the main engine class:

When I set up the script engine, I pass the address of my engine class instance in as userdata (a void pointer):

[CODE]
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetUserData(&myGameEngine);
[/CODE]

Then, in my class constructors that need a pointer to the engine (to access window drawing, content management, etc.), I do this:

[CODE]
asIScriptContext* context = NULL;
asIScriptEngine* engine = NULL;
context = asGetActiveContext(); // Get the currently executing angelscript context
if ((context = asGetActiveContext()) != NULL && (engine = context->GetEngine()) != NULL)
{
// owner is a member pointer to the engine
owner = reinterpret_cast<Engine*>(engine->GetUserData());
}
[/CODE]

Hopefully that helps. Edited by Jake Albano

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='Jake Albano' timestamp='1348947598' post='4985130']
Here's how I give my classes access to the main engine class:

When I set up the script engine, I pass the address of my engine class instance in as userdata (a void pointer):

[CODE]
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetUserData(&myGameEngine);
[/CODE]

Then, in my class constructors that need a pointer to the engine (to access window drawing, content management, etc.), I do this:

[CODE]
asIScriptContext* context = NULL;
asIScriptEngine* engine = NULL;
context = asGetActiveContext(); // Get the currently executing angelscript context
if ((context = asGetActiveContext()) != NULL && (engine = context->GetEngine()) != NULL)
{
// owner is a member pointer to the engine
owner = reinterpret_cast<Engine*>(engine->GetUserData());
}
[/CODE]

Hopefully that helps.
[/quote]

Gonna try that but here is my engine class

[CODE]
#include "Engine.h"
#include <windows.h> // For the WaitMessage() function.
#include "Scripting/ScriptManager.h"
using namespace Ogre;
/** Default constructor. **/
AffinityEngine::AffinityEngine() {
m_lLastTick = 0;
m_iWidth = 1024;
m_iHeight = 768;
m_czTitle = 0;
m_pScreen = 0;
m_iFPSTickCounter = 0;
m_iFPSCounter = 0;
m_iCurrentFPS = 0;
m_bMinimized = false;
}
/** Destructor. **/
AffinityEngine::~AffinityEngine() {
SDL_Quit();
}
/** Sets the height and width of the window.
@param iWidth The width of the window
@param iHeight The height of the window
**/
void AffinityEngine::SetSize(const int& iWidth, const int& iHeight) {
m_iWidth = iWidth;
m_iHeight = iHeight;
if(m_vmVideoMode == VideoMode_3D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_OPENGL );
} else if(m_vmVideoMode == VideoMode_2D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_SWSURFACE );
}
}
/** Initialize SDL, the window and the additional data. **/
void AffinityEngine::Init(VideoMode videoMode) {
printf("Engine Initialing.\n");
// Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit.
atexit( SDL_Quit );
// Initialize SDL's subsystems - in this case, only video.
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf( stderr, "Unable to init SDL: %s\n", SDL_GetError() );
exit( 1 );
}
SetTitle("Affinity Engine");
m_vmVideoMode = videoMode;
// Attempt to create a window with the specified height and width.
SetSize(m_iWidth, m_iHeight);
if(videoMode == VideoMode_3D){
m_rRoot = new Root("plugins_d.cfg", "ogre.cfg", "AffinityEngine.log");
m_rRoot->restoreConfig();
m_rRoot->initialise(false);
NameValuePairList misc;
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWMInfo(&wmInfo);

size_t winHandle = reinterpret_cast<size_t>(wmInfo.window);
size_t winGlContext = reinterpret_cast<size_t>(wmInfo.hglrc);

misc["externalWindowHandle"] = StringConverter::toString(winHandle);
misc["externalGLContext"] = StringConverter::toString(winGlContext);
#else
misc["currentGLContext"] = String("True");
#endif
m_rwRenderWindow = m_rRoot->createRenderWindow("MainRenderWindow", 1024, 768, false, &misc);
m_rwRenderWindow->setVisible(true);
printf("Initialized 3D Rendering.\n");
} else {
printf("Initialized 2D Rendering.\n");
}
// If we fail, return error.
if ( m_pScreen == NULL ) {
fprintf( stderr, "Unable to set up video: %s\n", SDL_GetError() );
exit( 1 );
}
printf("Engine Initialized.\n");
AdditionalInit();
}
/** The main loop. **/
void AffinityEngine::Start() {
printf("Engine Started\n");
m_lLastTick = SDL_GetTicks();
m_bQuit = false;
m_smScriptManager = new ScriptManager("../Data/Scripts", this);
m_smScriptManager->Init();
// Main loop: loop forever.
while ( !m_bQuit ) {
// Handle mouse and keyboard input
HandleInput();
if ( m_bMinimized ) {
// Release some system resources if the app. is minimized.
WaitMessage(); // pause the application until focus in regained
} else {
// Do some thinking
DoLogic();
// Render stuff
DoRender();
}
}
End();
}
/** Handles all controller inputs.
@remark This function is called once per frame.
**/
void AffinityEngine::HandleInput() {
// Poll for events, and handle the ones we care about.
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
switch (event.type) {
case SDL_KEYDOWN:
// If escape is pressed set the Quit-flag
/*if (event.key.keysym.sym == SDLK_ESCAPE){
m_bQuit = true;
break;
}*/
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Down);
KeyDown(event.key.keysym.sym);
break;
case SDL_KEYUP:
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Up);
KeyUp(event.key.keysym.sym);
break;
case SDL_QUIT:
m_bQuit = true;
break;
case SDL_MOUSEMOTION:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseMoved(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONUP:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonUp(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONDOWN:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonDown(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_ACTIVEEVENT:
if ( event.active.state & SDL_APPACTIVE ) {
if ( event.active.gain ) {
m_bMinimized = false;
WindowActive();
} else {
m_bMinimized = true;
WindowInactive();
}
}
break;
} // switch
} // while (handling input)
}
/** Handles the updating routine. **/
void AffinityEngine::DoLogic() {
long iElapsedTicks = SDL_GetTicks() - m_lLastTick;
m_lLastTick = SDL_GetTicks();
m_smScriptManager->ParseScripts();
Logic( iElapsedTicks );
m_smScriptManager->Update();
m_iFPSTickCounter += iElapsedTicks;
}
/** Handles the rendering and FPS calculations. **/
void AffinityEngine::DoRender() {
++m_iFPSCounter;
if ( m_iFPSTickCounter >= 1000 ) {
m_iCurrentFPS = m_iFPSCounter;
m_iFPSCounter = 0;
m_iFPSTickCounter = 0;
}
if(m_vmVideoMode == VideoMode_2D) {
SDL_FillRect( m_pScreen, 0, SDL_MapRGB( m_pScreen->format, 0, 0, 0 ) );
// Lock surface if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
if ( SDL_LockSurface( m_pScreen ) < 0 )
return;
Render( GetSurface() );
m_smScriptManager->Draw();
// Unlock if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
SDL_UnlockSurface( m_pScreen );
// Tell SDL to update the whole gScreen
SDL_Flip( m_pScreen );
}else{
m_rRoot->renderOneFrame();
SDL_GL_SwapBuffers();
}
}
/** Sets the title of the window
@param czTitle A character array that contains the text that the window title should be set to.
**/
void AffinityEngine::SetTitle(std::string czTitle) {
m_czTitle = czTitle.c_str();
SDL_WM_SetCaption( czTitle.c_str(), 0 );
}
/** Retrieve the title of the application window.
@return The last set windows title as a character array.
@remark Only the last set title is returned. If another application has changed the window title, then that title won't be returned.
**/
const char* AffinityEngine::GetTitle() {
return m_czTitle;
}
/** Retrieve the main screen surface.
@return A pointer to the SDL_Surface surface
@remark The surface is not validated internally.
**/
SDL_Surface* AffinityEngine::GetSurface() {
return m_pScreen;
}
/** Get the current FPS.
@return The number of drawn frames in the last second.
@remark The FPS is only updated once each second.
**/
int AffinityEngine::GetFPS() {
return m_iCurrentFPS;
}
void AffinityEngine::Shutdown() {
m_bQuit = true;
}
ScriptManager* AffinityEngine::GetScriptManager() {
return m_smScriptManager;
}
[/CODE]

Ok while making those changes I got this error:

[CODE]Engine Initialing.
Initialized 2D Rendering.
Engine Initialized.
Engine Started
(0, 0) : ERR : Failed in call to function 'RegisterObjectBehaviour' with 'Imag
e' and 'ref@ f()' (Code: -10)[/CODE]

from this line

[CODE]
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "ref@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);
[/CODE]

and here is the function:

[CODE]
static Img* Img_Factory() {
return new Img();
}
[/CODE] Edited by Fayte

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='Fayte' timestamp='1348953565' post='4985160']
[quote name='Jake Albano' timestamp='1348947598' post='4985130']
Here's how I give my classes access to the main engine class:

When I set up the script engine, I pass the address of my engine class instance in as userdata (a void pointer):

[CODE]
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetUserData(&myGameEngine);
[/CODE]

Then, in my class constructors that need a pointer to the engine (to access window drawing, content management, etc.), I do this:

[CODE]
asIScriptContext* context = NULL;
asIScriptEngine* engine = NULL;
context = asGetActiveContext(); // Get the currently executing angelscript context
if ((context = asGetActiveContext()) != NULL && (engine = context->GetEngine()) != NULL)
{
// owner is a member pointer to the engine
owner = reinterpret_cast<Engine*>(engine->GetUserData());
}
[/CODE]

Hopefully that helps.
[/quote]

Gonna try that but here is my engine class

[CODE]
#include "Engine.h"
#include <windows.h> // For the WaitMessage() function.
#include "Scripting/ScriptManager.h"
using namespace Ogre;
/** Default constructor. **/
AffinityEngine::AffinityEngine() {
m_lLastTick = 0;
m_iWidth = 1024;
m_iHeight = 768;
m_czTitle = 0;
m_pScreen = 0;
m_iFPSTickCounter = 0;
m_iFPSCounter = 0;
m_iCurrentFPS = 0;
m_bMinimized = false;
}
/** Destructor. **/
AffinityEngine::~AffinityEngine() {
SDL_Quit();
}
/** Sets the height and width of the window.
@param iWidth The width of the window
@param iHeight The height of the window
**/
void AffinityEngine::SetSize(const int& iWidth, const int& iHeight) {
m_iWidth = iWidth;
m_iHeight = iHeight;
if(m_vmVideoMode == VideoMode_3D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_OPENGL );
} else if(m_vmVideoMode == VideoMode_2D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_SWSURFACE );
}
}
/** Initialize SDL, the window and the additional data. **/
void AffinityEngine::Init(VideoMode videoMode) {
printf("Engine Initialing.\n");
// Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit.
atexit( SDL_Quit );
// Initialize SDL's subsystems - in this case, only video.
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf( stderr, "Unable to init SDL: %s\n", SDL_GetError() );
exit( 1 );
}
SetTitle("Affinity Engine");
m_vmVideoMode = videoMode;
// Attempt to create a window with the specified height and width.
SetSize(m_iWidth, m_iHeight);
if(videoMode == VideoMode_3D){
m_rRoot = new Root("plugins_d.cfg", "ogre.cfg", "AffinityEngine.log");
m_rRoot->restoreConfig();
m_rRoot->initialise(false);
NameValuePairList misc;
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWMInfo(&wmInfo);

size_t winHandle = reinterpret_cast<size_t>(wmInfo.window);
size_t winGlContext = reinterpret_cast<size_t>(wmInfo.hglrc);

misc["externalWindowHandle"] = StringConverter::toString(winHandle);
misc["externalGLContext"] = StringConverter::toString(winGlContext);
#else
misc["currentGLContext"] = String("True");
#endif
m_rwRenderWindow = m_rRoot->createRenderWindow("MainRenderWindow", 1024, 768, false, &misc);
m_rwRenderWindow->setVisible(true);
printf("Initialized 3D Rendering.\n");
} else {
printf("Initialized 2D Rendering.\n");
}
// If we fail, return error.
if ( m_pScreen == NULL ) {
fprintf( stderr, "Unable to set up video: %s\n", SDL_GetError() );
exit( 1 );
}
printf("Engine Initialized.\n");
AdditionalInit();
}
/** The main loop. **/
void AffinityEngine::Start() {
printf("Engine Started\n");
m_lLastTick = SDL_GetTicks();
m_bQuit = false;
m_smScriptManager = new ScriptManager("../Data/Scripts", this);
m_smScriptManager->Init();
// Main loop: loop forever.
while ( !m_bQuit ) {
// Handle mouse and keyboard input
HandleInput();
if ( m_bMinimized ) {
// Release some system resources if the app. is minimized.
WaitMessage(); // pause the application until focus in regained
} else {
// Do some thinking
DoLogic();
// Render stuff
DoRender();
}
}
End();
}
/** Handles all controller inputs.
@remark This function is called once per frame.
**/
void AffinityEngine::HandleInput() {
// Poll for events, and handle the ones we care about.
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
switch (event.type) {
case SDL_KEYDOWN:
// If escape is pressed set the Quit-flag
/*if (event.key.keysym.sym == SDLK_ESCAPE){
m_bQuit = true;
break;
}*/
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Down);
KeyDown(event.key.keysym.sym);
break;
case SDL_KEYUP:
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Up);
KeyUp(event.key.keysym.sym);
break;
case SDL_QUIT:
m_bQuit = true;
break;
case SDL_MOUSEMOTION:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseMoved(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONUP:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonUp(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONDOWN:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonDown(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_ACTIVEEVENT:
if ( event.active.state & SDL_APPACTIVE ) {
if ( event.active.gain ) {
m_bMinimized = false;
WindowActive();
} else {
m_bMinimized = true;
WindowInactive();
}
}
break;
} // switch
} // while (handling input)
}
/** Handles the updating routine. **/
void AffinityEngine::DoLogic() {
long iElapsedTicks = SDL_GetTicks() - m_lLastTick;
m_lLastTick = SDL_GetTicks();
m_smScriptManager->ParseScripts();
Logic( iElapsedTicks );
m_smScriptManager->Update();
m_iFPSTickCounter += iElapsedTicks;
}
/** Handles the rendering and FPS calculations. **/
void AffinityEngine::DoRender() {
++m_iFPSCounter;
if ( m_iFPSTickCounter >= 1000 ) {
m_iCurrentFPS = m_iFPSCounter;
m_iFPSCounter = 0;
m_iFPSTickCounter = 0;
}
if(m_vmVideoMode == VideoMode_2D) {
SDL_FillRect( m_pScreen, 0, SDL_MapRGB( m_pScreen->format, 0, 0, 0 ) );
// Lock surface if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
if ( SDL_LockSurface( m_pScreen ) < 0 )
return;
Render( GetSurface() );
m_smScriptManager->Draw();
// Unlock if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
SDL_UnlockSurface( m_pScreen );
// Tell SDL to update the whole gScreen
SDL_Flip( m_pScreen );
}else{
m_rRoot->renderOneFrame();
SDL_GL_SwapBuffers();
}
}
/** Sets the title of the window
@param czTitle A character array that contains the text that the window title should be set to.
**/
void AffinityEngine::SetTitle(std::string czTitle) {
m_czTitle = czTitle.c_str();
SDL_WM_SetCaption( czTitle.c_str(), 0 );
}
/** Retrieve the title of the application window.
@return The last set windows title as a character array.
@remark Only the last set title is returned. If another application has changed the window title, then that title won't be returned.
**/
const char* AffinityEngine::GetTitle() {
return m_czTitle;
}
/** Retrieve the main screen surface.
@return A pointer to the SDL_Surface surface
@remark The surface is not validated internally.
**/
SDL_Surface* AffinityEngine::GetSurface() {
return m_pScreen;
}
/** Get the current FPS.
@return The number of drawn frames in the last second.
@remark The FPS is only updated once each second.
**/
int AffinityEngine::GetFPS() {
return m_iCurrentFPS;
}
void AffinityEngine::Shutdown() {
m_bQuit = true;
}
ScriptManager* AffinityEngine::GetScriptManager() {
return m_smScriptManager;
}
[/CODE]

Ok while making those changes I got this error:

[CODE]Engine Initialing.
Initialized 2D Rendering.
Engine Initialized.
Engine Started
(0, 0) : ERR : Failed in call to function 'RegisterObjectBehaviour' with 'Imag
e' and 'ref@ f()' (Code: -10)[/CODE]

from this line

[CODE]
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "ref@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);
[/CODE]

and here is the function:

[CODE]
static Img* Img_Factory() {
return new Img();
}
[/CODE]
[/quote]

Once I get my game running again I can test to see if the changes worked. (Sorry for the double post meant to edit >.<) Edited by Fayte

Share this post


Link to post
Share on other sites
TechRogue    722
You'll want to do it like this:

[CODE]
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "Image@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);
[/CODE]

Using "image" instead of "ref".

Share this post


Link to post
Share on other sites
saejox    714
i might be missing the point here but wouldn't singleton engine class solve this?

[CODE]
class Engine
{
private:
Engine::Engine();
static Engine *instance;
public:
static Engine *get()
{
if (!instance)
instance = new Engine;
return instance;
}
void init()
{
// Do init.
}
}
Engine* Engine::instance = 0;
[/CODE]

they you will have access to it anywhere anytime.

Share this post


Link to post
Share on other sites
saejox    714
a very wrong misconception.
singletons are definitely not global variables. you cant control access with global variables.

the way you do it is more akin to a global variable.
it makes engine to accessible and volatile to every piece of code in your program.

what if some evil soul decides to call asGetActiveContext()->GetEngine()->SetUserdata(null);
angry employee maybe?

Share this post


Link to post
Share on other sites
TechRogue    722
I strongly suggest you read this article: [url="http://gameprogrammingpatterns.com/singleton.html"]http://gameprogrammi.../singleton.html[/url] Singletons have a lot of attractive features at first glance, but they're really a bad idea in the long run.

I do understand the difference between a plain global and the singleton pattern, but functionally they serve the same purpose of providing global access to the same variable anywhere in your program. Additionally, my engine is designed so I could have multiple instances of it running in the same program. Using a singleton for the engine would prevent me from doing this.

As far as malicious use goes (although I'm not sure why that would ever be a concern), your singleton example above is just as susceptible:

[CODE]
delete Engine::get();
[/CODE]

To each his own. Let's not go any further off topic. :)

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='saejox' timestamp='1348960828' post='4985184']
i might be missing the point here but wouldn't singleton engine class solve this?

[CODE]
class Engine
{
private:
Engine::Engine();
static Engine *instance;
public:
static Engine *get()
{
if (!instance)
instance = new Engine;
return instance;
}
void init()
{
// Do init.
}
}
Engine* Engine::instance = 0;
[/CODE]

they you will have access to it anywhere anytime.
[/quote]

Ok the singleton thing to me is a relatively new concept I can do it in C# but C++ eludes me.

Here is the game class that inherits from the engine class and I added your singleton code to it:

[CODE]
#ifndef GAME_H
#define GAME_H
#include "Engine\Engine.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <string>
#include <iostream>
/*
#ifdef _MSC_VER
#include <crtdbg.h> // debugging routines
#endif
*/
using namespace std;

class Game : public AffinityEngine {
private:
static Game *instance;
public:
Game();
~Game();
void AdditionalInit ();
void Logic (const int& iElapsedTime );
void Render (SDL_Surface* pDestSurface );

void KeyUp (const int& iKeyEnum);
void KeyDown (const int& iKeyEnum);

void MouseMoved (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY);

void MouseButtonUp (const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY);

void MouseButtonDown(const int& iButton, const int& iX, const int& iY, const int& iRelX, const int& iRelY);

void WindowInactive ();
void WindowActive ();

void End ();
void Setup ();
static Game *get() {
if (!instance){
instance = new Game;
}
return instance;
}
};
Game::Game() {
instance = this;
}
Game::~Game() {
//delete m_smScriptManager;
}
void Game::Setup() {
}
#endif
[/CODE]

when I compile I get this:

[CODE]
1>ScriptManager.obj : error LNK2005: "public: void __thiscall Game::Setup(void)" (?Setup@Game@@QAEXXZ) already defined in Engine.obj
1>ScriptManager.obj : error LNK2005: "public: virtual __thiscall Game::~Game(void)" (??1Game@@UAE@XZ) already defined in Engine.obj
1>ScriptManager.obj : error LNK2005: "public: __thiscall Game::Game(void)" (??0Game@@QAE@XZ) already defined in Engine.obj
1>Img.obj : error LNK2005: "public: void __thiscall Game::Setup(void)" (?Setup@Game@@QAEXXZ) already defined in Engine.obj
1>Img.obj : error LNK2005: "public: virtual __thiscall Game::~Game(void)" (??1Game@@UAE@XZ) already defined in Engine.obj
1>Img.obj : error LNK2005: "public: __thiscall Game::Game(void)" (??0Game@@QAE@XZ) already defined in Engine.obj
1>main.obj : error LNK2005: "public: void __thiscall Game::Setup(void)" (?Setup@Game@@QAEXXZ) already defined in Engine.obj
1>main.obj : error LNK2005: "public: virtual __thiscall Game::~Game(void)" (??1Game@@UAE@XZ) already defined in Engine.obj
1>main.obj : error LNK2005: "public: __thiscall Game::Game(void)" (??0Game@@QAE@XZ) already defined in Engine.obj
1> Creating library C:\Users\Xios\Documents\Visual Studio 2010\Projects\AffinityEngine-Oblivion\Debug\AffinityEngine-Oblivion.lib and object C:\Users\Xios\Documents\Visual Studio 2010\Projects\AffinityEngine-Oblivion\Debug\AffinityEngine-Oblivion.exp
1>MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>Engine.obj : error LNK2001: unresolved external symbol "private: static class Game * Game::instance" (?instance@Game@@0PAV1@A)
[/CODE]

turns out it was because I had a couple of my functions implemented in the .h file now I only have:

[CODE]
Game.obj : error LNK2001: unresolved external symbol "private: static class Game * Game::instance" (?instance@Game@@0PAV1@A)
[/CODE]

That was fixed by making a Game.cpp and putting this in it.

[CODE]
Game* Game::instance = 0;
Game::Game() {
Game::instance = this;
}
[/CODE]

just helping others with the same issue later.

Now I don't get any errors from the program or the script but my image doesn't show up. If I had to wager a guess it's that the image class still is not getting the right engine instance regardless of the singleton. Is my script running on a separate thread? Is that the issue because I have not specifically tried. I would have to assume this is correct because when I try this:

[CODE]
image = new Img();
image->X = 0;
image->Y = 0;
image->fileName = "AyphixPresents.png";
[/CODE]

inside of C++ it works great. Which is essentially the same thing my script does when I do this:

[CODE]
class GameManager {
string GameTitle;
bool quit;
Image@ img;
GameManager(string gameTitle) {
quit = false;
GameTitle = GameTitle;
Application.SetTitle(gameTitle);
@img = Image();
img.X = 0;
img.Y = 0;
img.Filename = "../Data/Images/AyphixPresents.png";
}
void Update() {
if(Input.GetKeyDown(Keycode::Escape)){
Application.Exit();
}
//img.draw();
}
}
[/CODE]


Problem solved :)

[CODE]
r = e_seScriptEngine->RegisterObjectProperty("Image", "int Y", asOFFSET(Img, Y)); assert(r >= 0);
[/CODE]
asOFFSET(Img, Y) was asOFFSET(Img, X) when I changed it, it worked. Thanks to both of you for the help! Edited by Fayte

Share this post


Link to post
Share on other sites
Fayte    139
Ok one last question before I call this success :)

I want to be able to pass my x y and filename into my constructor;

But my factory looks like this with no clue what angelscript is passing into the constructor.

[CODE]
static Img* Img_Factory() {
return new Img();
}
[/CODE]

Does it really matter what my factory has? Will I will be able to register a constructor with those in it?

Share this post


Link to post
Share on other sites
TechRogue    722
Yes, this is possible. You can register multiple constructors for a class:

You'll need separate factory functions:
[CODE]
static Img* Img_Factory() {
return new Img();
}

static Img* Img_Factory(int x, int y) {
return new Img(int x, int y);
}
[/CODE]

And register them this way:
[CODE]
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "Image@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "Image@ f(int, int)", asFUNCTIONPR(Img_Factory, (int, int), Img*), asCALL_CDECL); assert(r >= 0);
[/CODE]

asFUNCTIONPR lets you distinguish between overloaded functions.
http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_func.html

Share this post


Link to post
Share on other sites
Fayte    139
[quote name='Jake Albano' timestamp='1349012050' post='4985348']
Yes, this is possible. You can register multiple constructors for a class:

You'll need separate factory functions:
[CODE]
static Img* Img_Factory() {
return new Img();
}

static Img* Img_Factory(int x, int y) {
return new Img(int x, int y);
}
[/CODE]

And register them this way:
[CODE]
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "Image@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);
r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "Image@ f(int, int)", asFUNCTIONPR(Img_Factory, (int, int), Img*), asCALL_CDECL); assert(r >= 0);
[/CODE]

asFUNCTIONPR lets you distinguish between overloaded functions.
[url="http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_func.html"]http://www.angelcode...ister_func.html[/url]
[/quote]

:) Thanks a ton for all the help.

Share this post


Link to post
Share on other sites
saejox    714
[quote name='Jake Albano' timestamp='1348964268' post='4985198']
I strongly suggest you read this article: [url="http://gameprogrammingpatterns.com/singleton.html"]http://gameprogrammi.../singleton.html[/url] Singletons have a lot of attractive features at first glance, but they're really a bad idea in the long run.

I do understand the difference between a plain global and the singleton pattern, but functionally they serve the same purpose of providing global access to the same variable anywhere in your program. Additionally, my engine is designed so I could have multiple instances of it running in the same program. Using a singleton for the engine would prevent me from doing this.

As far as malicious use goes (although I'm not sure why that would ever be a concern), your singleton example above is just as susceptible:

[CODE]
delete Engine::get();
[/CODE]

To each his own. Let's not go any further off topic. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]

[CODE]
protected:
friend void Game::EndGame();
~Engine();
[/CODE]

now only Game::EndGame() can call delete on singleton. applies to "get" and any other functions too.

Share this post


Link to post
Share on other sites
TechRogue    722
Come on now, this isn't the place for this discussion. You're not going to convince me that Singletons are a good idea, and I'm clearly not going to convince you that they're a bad one. Just let it go.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this