Intro oficial para videojuegos programados con Bennu

Started by Windgate, October 21, 2009, 01:14:06 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Prg

:) te podría ayudar linkernel que es el autor :)
descargando...
en humos puedes mover la camara con los cursores. es necesario para los niveles a partir del dos :)

DCelso

el dll está en el directorio release por si es lo que quieres probar.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

No sabía que fuese de linkernel. He probado la dll de video con la intro de bennu en un portatil atlonxp2800 con un giga de ram y va lentíisimo pero lentíiisimo, algo falla en la dll, ya que el video a través de un reproductor como videolan va perfectamente.
Splinter y linkernel, ¿podríais mirar el código fuente por encima para buscar optimizaciones?
Gracias de antemano.

/*
(C) 2004    Colombian Developers
License GNU/GPL
*/

#include <stdio.h>
#include <stdlib.h>

#include <math.h>
#include <memory.h>

#ifdef TARGET_BEOS
#include <posix/assert.h>
#else
#include <assert.h>
#endif


#include <windows.h>

//DIRECTX functions
#include <dshow.h>
#include <mmstream.h>
#include <amstream.h>
#include <ddstream.h>

//SDL functions
#include <SDL.h>
#include <SDL_syswm.h>//SDL stuff (for getting windows etc)

//BennuGD functions
#include "bgddl.h"

extern "C" const char * string_get( int code ) ;
extern "C" void         string_discard( int code ) ;

//-------

HINSTANCE hDLL = NULL;

#define true TRUE
#define false FALSE

#if defined(__GNUC__)
#define M_DLLAPI    WINAPI *    //devcpp
#else
#define M_DLLAPI    __cdecl  *  //visual c++
#endif

typedef const char * (M_DLLAPI tstrget)(int code);
typedef void (M_DLLAPI tstrdiscard)(int code);

//---------------------------------------------------
//FUNCIONES PPALES
//---------------------------------------------------

//dependencias DX8
int render_my_video(HWND hWnd, char *cadena, ...);
void close_my_video();

// init DirectShow pointers
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaSeeking * pSeek = NULL;
IVideoWindow *pVW;
IMediaEventEx * g_pME = NULL;
int salida = false;

static int f_Inicializar(INSTANCE * my, int * params) {

SDL_SysWMinfo wmInfo;
HWND MiV;
const char *Archivo = string_get(params[0]);
char cadena[255];
int retorno;

SDL_VERSION(&wmInfo.version);
SDL_GetWMInfo(&wmInfo);
MiV = wmInfo.window;

strcpy(cadena, Archivo);

retorno = render_my_video(MiV, cadena);

//liberar memoria
string_discard(params[0]);

close_my_video();

ShowWindow(MiV, SW_RESTORE);
SetCapture(MiV);
SetFocus(MiV);

return retorno;
}

//static int f_run(INSTANCE * my, int * params) {
// pControl->Run();
// return 0;
//}
//static int f_pause(INSTANCE * my, int * params) {
// pControl->Pause();
// return 0;
//}
//static int f_stop(INSTANCE * my, int * params) {
// salida=true;
// pControl->Stop();
// return 0;
//}


#include <stdio.h>
#include <tchar.h>

long FAR PASCAL WindowProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
switch( message )
{
// Monitor keystrokes for manipulating video window
// and program options
case WM_KEYDOWN:
switch( wParam )
{
case VK_ESCAPE:
case VK_SPACE:
case VK_RETURN:
salida=true;
pControl->Stop();

break;
}
break;

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hWnd, message, wParam, lParam);
}

int render_my_video(HWND hWnd, char *cadena, ...) {
HWND ventanaEventos;

#define CUTSCENE_NAME  TEXT("BGD SCENE")

WNDCLASS wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = 0;
wc.lpszClassName = CUTSCENE_NAME;
if (!RegisterClass(&wc))
return FALSE;

ventanaEventos = CreateWindowEx(0, CUTSCENE_NAME, "BGD SCENE", 0, // not visible
0, 0, 0, 0, NULL, NULL, 0, NULL); //crea una ventana para eventos del teclado

// init COM client/server
CoInitialize(NULL);
CoCreateInstance((REFCLSID) CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
(REFIID)IID_IGraphBuilder, (PVOID*) &pGraph);
// get DirectShow interfaces
pGraph->QueryInterface(IID_IMediaControl, (void **) &pControl);
pGraph->QueryInterface(IID_IMediaEventEx, (void **) &g_pME);
pGraph->QueryInterface(IID_IMediaSeeking, (void **) &pSeek);
pGraph->QueryInterface(IID_IVideoWindow, (void **) &pVW);

WCHAR wFile[MAX_PATH];
TCHAR szBuffer[255];

va_list pArgs;
va_start(pArgs, cadena);
vsprintf(szBuffer, cadena, pArgs);
va_end(pArgs);


// If the characters are in UNICODE we need parse they.
#ifndef UNICODE
MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, wFile, MAX_PATH);
#else
lstrcpy(wFile, szBuffer);
#endif

// init render (passing movie file)
pGraph->RenderFile(wFile, NULL);

// make parent
pVW->put_Owner((OAHWND) hWnd);

#define WM_GRAPHNOTIFY  WM_APP+1

//manda los eventos a la ventana oculta, el video lo manda a BennuGD
//g_pME->SetNotifyWindow((OAHWND)ventanaEventos, WM_GRAPHNOTIFY, 0);
HRESULT hr = pVW->put_MessageDrain((OAHWND) ventanaEventos);
if (FAILED(hr))
return false;

// Adjust "movie render window" to "bgd render window" dimensions
RECT grc;
GetClientRect(hWnd, &grc);
pVW->SetWindowPosition(0, 0, grc.right, grc.bottom);
pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

// keep focus in bgd
SetFocus(hWnd);
SetCapture(ventanaEventos);

pVW->put_Visible(OATRUE);

pControl->Run();

ShowWindow(hWnd, SW_RESTORE); //x si pierde el foco

MSG msg;

//crea un control independiente de los eventos , bgd queda aislado x el momento
//con el proposito que el sonido y el video se reproducen en tiempo real
// Check and process window messages (like our keystrokes)
while (!salida) {
while (PeekMessage(&msg, ventanaEventos, 0, 0, PM_REMOVE)) {
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);

TranslateMessage(&msg);
DispatchMessage(&msg);
}

long lEventCode, lParam1, lParam2;

// Has there been a media event?  Look for end of stream condition.
if (E_ABORT != g_pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) {
// Free the media event resources.
hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2);
if (FAILED(hr)) {
salida = true;
}

// Is this the end of the movie?
if (lEventCode == EC_COMPLETE) {
salida = true;
}
}

}

DestroyWindow(ventanaEventos);

return true;
}

void close_my_video() {
// release
pControl->Stop();
pVW->put_Visible(OAFALSE);
pVW->put_Owner(0);
pVW->Release();
pSeek->Release();
pControl->Release();
g_pME->Release();
pGraph->Release();
CoUninitialize();

}

DLSYSFUNCS __bgdexport(mod_dshow,functions_exports)[] = {
    { "PLAY_VIDEO"               , "S"   , TYPE_DWORD  , (void*) f_Inicializar             },
//     { "RUN_VIDEO"               , ""   , TYPE_INT  , (void*) f_run             },
//     { "PAUSE_VIDEO"               , ""   , TYPE_INT  , (void*) f_pause             },
//     { "STOP_VIDEO"               , ""   , TYPE_INT  , (void*) f_stop             },
    { 0                     , 0         , 0         , 0                     }
};

/* ----------------------------------------------------------------- */

/* Bigest priority first execute
Lowest priority last execute */

char * __bgdexport(mod_dshow,modules_dependency)[] =
{
"libsdlhandler",
"mod_string",
NULL
};


Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

SplinterGU

ya lo vi hace mucho, ese codigo solo funciona con compilador msvc...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

Pues ya no, yo lo he adaptado para compilar con gcc, si te bajas mi adjunto verás el proyecto en eclipse.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

SplinterGU

pero compila? yo recuerdo que fallaba por la falta de dlls...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

clarop, tengo el dll creado con gcc y probado y funcionando, si te bajas el documento lo verás en la carpeta release.
Las dependencias son un .lib de directx que adjunto y los dlls de ole32 de windows y el bgdrtm de bennu.

El problema radica en que el código es muy complejo para mí, entiendo algunas cosas pero no todas, hace algo muy extraño como que se trae el manejador de SDL y sustituye el controlador de eventos por uno propio, y esto es lo que me parece a mi que la caga porque elimina el control de teclado de bennu.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Si examinas el código, añadí tres funciones nuevas de parada, pausa y resumen pero no van por eso las comenté para que no se exportaran.
Creo que no van por lo explicado anteriormente del teclado.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Hola Splinter, he reducido considerablemente el código a lo esencial e indispensable, ahora va un poquito más rápido pero sigue yendo un poco lento. He eliminado toda la parte que comentaba antes de un control de teclas de una ventana invisible o algo así, el código queda reducido a lo siguiente:

/*
(C) 2004    Colombian Developers
License GNU/GPL
*/

#include <stdio.h>
#include <stdlib.h>

#include <math.h>
#include <memory.h>

#ifdef TARGET_BEOS
#include <posix/assert.h>
#else
#include <assert.h>
#endif


#include <windows.h>

//DIRECTX functions
#include <dshow.h>
#include <mmstream.h>
#include <amstream.h>
#include <ddstream.h>

//SDL functions
#include <SDL.h>
#include <SDL_syswm.h>//SDL stuff (for getting windows etc)

//BennuGD functions
#include "bgddl.h"

extern "C" const char * string_get( int code ) ;
extern "C" void         string_discard( int code ) ;

//-------

HINSTANCE hDLL = NULL;

#define true TRUE
#define false FALSE

#if defined(__GNUC__)
#define M_DLLAPI    WINAPI *    //devcpp
#else
#define M_DLLAPI    __cdecl  *  //visual c++
#endif

typedef const char * (M_DLLAPI tstrget)(int code);
typedef void (M_DLLAPI tstrdiscard)(int code);

//---------------------------------------------------
//FUNCIONES PPALES
//---------------------------------------------------

//dependencias DX8
int render_my_video(HWND hWnd, char *cadena);
void close_my_video();

// init DirectShow pointers
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
//IMediaSeeking * pSeek = NULL;
IVideoWindow *pVW;
IMediaEventEx * g_pME = NULL;
int salida = false;

static int f_Inicializar(INSTANCE * my, int * params) {

SDL_SysWMinfo wmInfo;
HWND MiV;
const char *Archivo = string_get(params[0]);
char cadena[255];
int retorno;

SDL_VERSION(&wmInfo.version);
SDL_GetWMInfo(&wmInfo);
MiV = wmInfo.window;

strcpy(cadena, Archivo);

retorno = render_my_video(MiV, cadena);

//liberar memoria
string_discard(params[0]);

close_my_video();

ShowWindow(MiV, SW_RESTORE);
SetCapture(MiV);
SetFocus(MiV);

return retorno;
}

static int f_run(INSTANCE * my, int * params) {
pControl->Run();
return 0;
}
static int f_pause(INSTANCE * my, int * params) {
pControl->Pause();
return 0;
}
static int f_stop(INSTANCE * my, int * params) {
salida=true;
pControl->Stop();
return 0;
}

int render_my_video(HWND hWnd, char *cadena) {
// init COM client/server
CoInitialize(NULL);
CoCreateInstance((REFCLSID) CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
(REFIID)IID_IGraphBuilder, (PVOID*) &pGraph);
// get DirectShow interfaces
pGraph->QueryInterface(IID_IMediaControl, (void **) &pControl);
pGraph->QueryInterface(IID_IMediaEventEx, (void **) &g_pME);
//pGraph->QueryInterface(IID_IMediaSeeking, (void **) &pSeek);
pGraph->QueryInterface(IID_IVideoWindow, (void **) &pVW);

WCHAR wFile[MAX_PATH];

// If the characters are in UNICODE we need parse they.
#ifndef UNICODE
MultiByteToWideChar(CP_ACP, 0, cadena, -1, wFile, MAX_PATH);
#else
lstrcpy(wFile, cadena);
#endif

// init render (passing movie file)
pGraph->RenderFile(wFile, NULL);

// make parent
pVW->put_Owner((OAHWND) hWnd);

// Adjust "movie render window" to "bgd render window" dimensions
RECT grc;
GetClientRect(hWnd, &grc);
pVW->SetWindowPosition(0, 0, grc.right, grc.bottom);
pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

pControl->Run();
    // Loop that show the video
while (!salida) {

long lEventCode, lParam1, lParam2;

// Has there been a media event?  Look for end of stream condition.
if (E_ABORT != g_pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) {
// Free the media event resources.
HRESULT hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2);
if (FAILED(hr)) {
salida = true;
}

// Is this the end of the movie?
if (lEventCode == EC_COMPLETE) {
salida = true;
}
}

}

return true;
}

void close_my_video() {
// release
pControl->Stop();
pVW->Release();
//pSeek->Release();
pControl->Release();
g_pME->Release();
pGraph->Release();
CoUninitialize();

}

DLSYSFUNCS __bgdexport(mod_dshow,functions_exports)[] = {
    { "PLAY_VIDEO"               , "S"   , TYPE_DWORD  , (void*) f_Inicializar             },
    { "RUN_VIDEO"               , ""   , TYPE_INT  , (void*) f_run             },
    { "PAUSE_VIDEO"               , ""   , TYPE_INT  , (void*) f_pause             },
    { "STOP_VIDEO"               , ""   , TYPE_INT  , (void*) f_stop             },
    { 0                     , 0         , 0         , 0                     }
};

/* ----------------------------------------------------------------- */

/* Bigest priority first execute
Lowest priority last execute */

char * __bgdexport(mod_dshow,modules_dependency)[] =
{
"libsdlhandler",
"mod_string",
NULL
};



En la función play_video hay un bucle que se encarga de generar el video y este es el culpable de que el sistema se quede bloqueado hasta que se termine la ejecución.
Habría que encontrar una forma diferente de llevar a cabo esta tarea para que no fuese bloqueante, algo como ejecutar el contenido de esto en cada frame en vez de aqui del tirón.

    // Loop that show the video
while (!salida) {

long lEventCode, lParam1, lParam2;

// Has there been a media event?  Look for end of stream condition.
if (E_ABORT != g_pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) {
// Free the media event resources.
HRESULT hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2);
if (FAILED(hr)) {
salida = true;
}

// Is this the end of the movie?
if (lEventCode == EC_COMPLETE) {
salida = true;
}
}

}
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

SplinterGU

podes usar un thread o usar algun callback de bennu...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

podes usar un thread o usar algun callback de bennu...

¿Cuando se crea una DLL se pueden hacer uso de threads en C?

¿Entonces, los PROCESS que invocamos en Bennu no podrían también hacer uso de threads también?

No lo tengo claro del todo, pero tengo entendido que bgdi se ejecuta en un hilo único, ¿es así?
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Interesante, es difícil pasar un día por el foro sin aprender algo nuevo, lo archivo para cuando pueda sacarle utilidad.
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

lo que quise decir es que tenes las fpg_loadbg o algo asi... que son para cargar un fpg sin frenar la ejecucion.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Puede ser interesante, ahora mismo estaba empezando un proyecto con scroll tileado, y se podría plantear la idea de tener los tiles en varios fpgs e ir cargándolos en ejecución al tiempo que se desplaza.

En cualquier caso he mirado la function_list y buscado todas las funciones que tienen "load" "bg" y "fpg", pero no encuentro nada que se parezca a lo que me dices, sólo estas funciones que no conocía:

INT FPG_ADD(INTEGER, INTEGER, INTEGER, INTEGER)
INT FPG_LOAD(STRING, POINTER)
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es