#define ZGL_IMPORT #include #include #include "zglHeader.h" typedef struct { // RU: Обязательная часть нового типа спрайта. // EN: New type should start with this. ZGLTSPRITE2D // RU: Новые параметры. // EN: New params. zglTPoint2D Speed; } zglTMiku, *zglPMiku; zglPFont fntMain; zglPTexture texLogo; zglPTexture texMiku; int time; zglTSEngine2D sengine2d; char resource[256]; char* GetResource( char* FileName ) { #ifndef __MACOSX__ sprintf_s( resource, "../data/%s", FileName ); return resource; #else return FileName; #endif } // Miku void MikuInit( zglPMiku Miku ) { Miku->X = 800.0f + rand() % 800; Miku->Y = (float)( rand() % ( 600 - 128 ) ); // RU: Задаем скорость движения. // EN: Set the moving speed. Miku->Speed.X = -( rand() % 10 ) / 5.0f - 0.5f; Miku->Speed.Y = ( rand() % 10 - 5 ) / 5.0f; } void MikuDraw( zglPMiku Miku ) { asprite2d_Draw( Miku->Texture, Miku->X, Miku->Y, Miku->W, Miku->H, Miku->Angle, (ushort)Miku->Frame, Miku->Alpha, Miku->FxFlags ); } void MikuProc( zglPMiku Miku ) { Miku->X += Miku->Speed.X; Miku->Y += Miku->Speed.Y; Miku->Frame += ( abs( Miku->Speed.X ) + abs( Miku->Speed.Y ) ) / 25.0f; if ( Miku->Frame > 8 ) Miku->Frame = 1; // RU: Если спрайт выходит за пределы по X, сразу же удаляем его. // EN: Delete the sprite if it goes beyond X. if ( Miku->X < -128 ) sengine2d_DelSprite( Miku->ID ); // RU: Если спрайт выходит за пределы по Y, ставим его в очередь на удаление. // EN: Add sprite to queue for delete if it goes beyond Y. if ( Miku->Y < -128 ) Miku->Destroy = TRUE; if ( Miku->Y > 600 ) Miku->Destroy = TRUE; } void MikuFree( zglPMiku Miku ) { } // RU: Добавить 100 спрайтов. // EN: Add 100 sprites. void AddMiku() { // RU: При добавлении спрайта в менеджер спрайтов указывается текстура, слой(положение по Z) и указатели на основные функции - Инициализация, Рендер, Обработка и Уничтожение. // EN: For adding sprite to sprite engine must be set next parameters: texture, layer(Z-coordinate) and pointers to Initialization, Render, Process and Destroy functions. for ( int i = 1; i <= 100; i++ ) sengine2d_AddCustom( texMiku, sizeof( zglTMiku ), rand() % 10, (zglSpriteFunc)&MikuInit, (zglSpriteFunc)&MikuDraw, (zglSpriteFunc)&MikuProc, (zglSpriteFunc)&MikuFree ); } // RU: Удалить 100 спрайтов. // EN: Delete 100 sprites. void DelMiku() { if ( sengine2d.Count < 100 ) return; // RU: Удалим 100 спрайтов со случайным ID. // EN: Delete 100 sprites with random ID. for ( int i = 1; i <= 100; i++ ) sengine2d_DelSprite( rand() % sengine2d.Count ); } void Init() { texLogo = tex_LoadFromFile( GetResource( "zengl.png" ), TEX_NO_COLORKEY, TEX_DEFAULT_2D ); texMiku = tex_LoadFromFile( GetResource( "miku.png" ), TEX_NO_COLORKEY, TEX_DEFAULT_2D ); tex_SetFrameSize( &texMiku, 128, 128 ); // RU: Устанавливаем текущим менеджером спрайтов свой. // EN: Set own sprite engine as current. sengine2d_Set( &sengine2d ); // RU: Создадим 1000 спрайтов Miku-chan :) // EN: Create 1000 sprites of Miku-chan :) for ( int i = 0; i < 10; i++ ) AddMiku(); fntMain = font_LoadFromFile( GetResource( "font.zfi" ) ); } void Draw() { batch2d_Begin(); // RU: Рисуем все спрайты находящиеся в текущем спрайтовом менеджере. // EN: Render all sprites contained in current sprite engine. if ( time > 255 ) sengine2d_Draw(); if ( time <= 255 ) ssprite2d_Draw( texLogo, 400 - 256, 300 - 128, 512, 256, 0, time, FX_BLEND ); else if ( time < 510 ) { pr2d_Rect( 0, 0, 800, 600, 0x000000, 510 - time, PR2D_FILL ); ssprite2d_Draw( texLogo, 400 - 256, 300 - 128, 512, 256, 0, 510 - time, FX_BLEND ); } if ( time > 255 ) { char text[256]; pr2d_Rect( 0, 0, 256, 64, 0x000000, 200, PR2D_FILL ); sprintf_s( text, "FPS: %i", (int)zgl_Get( RENDER_FPS ) ); text_Draw( fntMain, 0, 0, text, 0 ); sprintf_s( text, "Sprites: %i", sengine2d.Count ); text_Draw( fntMain, 0, 20, text, 0 ); text_Draw( fntMain, 0, 40, "Up/Down - Add/Delete Miku :)", 0 ); } batch2d_End(); } void Timer() { time +=2; // RU: Выполняем обработку всех спрайтов в текущем спрайтовом менеджере. // EN: Process all sprites contained in current sprite engine. sengine2d_Proc(); // RU: По нажатию пробела очистить все спрайты. // EN: Delete all sprites if space was pressed. if ( key_Press( K_SPACE ) ) sengine2d_ClearAll(); if ( key_Press( K_UP ) ) AddMiku(); if ( key_Press( K_DOWN ) ) DelMiku(); if ( key_Press( K_ESCAPE ) ) zgl_Exit(); key_ClearState(); } void Quit() { // RU: Очищаем память от созданных спрайтов. // EN: Free allocated memory for sprites. sengine2d_Set( &sengine2d ); sengine2d_ClearAll(); } int main() { if ( !zglLoad( libZenGL ) ) return 0; srand( 0xDeaDBeeF ); timer_Add( (void*)&Timer, 16, FALSE, NULL ); timer_Add( (void*)&AddMiku, 1000, FALSE, NULL ); zgl_Reg( SYS_LOAD, (void*)&Init ); zgl_Reg( SYS_DRAW, (void*)&Draw ); zgl_Reg( SYS_EXIT, (void*)&Quit ); wnd_SetCaption( "08 - Sprite Engine" ); wnd_ShowCursor( TRUE ); scr_SetOptions( 800, 600, REFRESH_MAXIMUM, FALSE, FALSE ); zgl_Init( 0, 0 ); zglFree(); return 0; }