| @@ -0,0 +1,84 @@ | ||
| #include "Managers.h" | ||
|
|
||
| #include "Managers.h" | ||
| #include "ImageLibrary.h" | ||
| #include "Entities\Entities.h" | ||
|
|
||
| #include "CoreComponents.h" | ||
| #include "WorldView.h" | ||
| #include "segashared\CheckedMemory.h" | ||
| #include "segalib\EGA.h" | ||
| #include "segautils\Rect.h" | ||
| #include "segautils\Defs.h" | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| typedef struct{ | ||
| byte flag; | ||
| }TCursorComponent; | ||
|
|
||
| #define TComponentT TCursorComponent | ||
| #include "Entities\ComponentDeclTransient.h" | ||
|
|
||
| struct CursorManager_t{ | ||
| Manager m; | ||
| WorldView *view; | ||
| Entity *e; | ||
|
|
||
| Int2 dragStart; | ||
|
|
||
| byte boxColor; | ||
|
|
||
| vec(Int2) *dragBox; | ||
| }; | ||
|
|
||
| ImplManagerVTable(CursorManager) | ||
|
|
||
| CursorManager *createCursorManager(WorldView *view){ | ||
| CursorManager *out = checkedCalloc(1, sizeof(CursorManager)); | ||
| out->view = view; | ||
| out->m.vTable = CreateManagerVTable(CursorManager); | ||
|
|
||
| out->boxColor = 15; | ||
|
|
||
| return out; | ||
| } | ||
|
|
||
| void _destroy(CursorManager *self){ | ||
| checkedFree(self); | ||
| } | ||
| void _onDestroy(CursorManager *self, Entity *e){} | ||
| void _onUpdate(CursorManager *self, Entity *e){} | ||
|
|
||
| static void _updateDragBox(CursorManager *self, int x, int y){ | ||
|
|
||
| if (self->dragBox){ | ||
| *vecAt(Int2)(self->dragBox, 0) = (Int2){ self->dragStart.x, self->dragStart.y }; | ||
| *vecAt(Int2)(self->dragBox, 1) = (Int2){ x, self->dragStart.y }; | ||
| *vecAt(Int2)(self->dragBox, 2) = (Int2){ x, y }; | ||
| *vecAt(Int2)(self->dragBox, 3) = (Int2){ self->dragStart.x, y }; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| } | ||
|
|
||
| void cursorManagerCreateCursor(CursorManager *self){ | ||
| self->e = entityCreate(self->view->entitySystem); | ||
|
|
||
| COMPONENT_ADD(self->e, PositionComponent, 0, 0); | ||
| COMPONENT_ADD(self->e, ImageComponent, stringIntern("assets/img/cursor.ega")); | ||
| COMPONENT_ADD(self->e, TCursorComponent, 0); | ||
| COMPONENT_ADD(self->e, LayerComponent, LayerCursor); | ||
| entityUpdate(self->e); | ||
| } | ||
|
|
||
| void cursorManagerUpdate(CursorManager *self, int x, int y){ | ||
| PositionComponent *pc = entityGet(PositionComponent)(self->e); | ||
| if (pc){ | ||
| pc->x = x; | ||
| pc->y = y; | ||
| } | ||
|
|
||
| _updateDragBox(self, x, y); | ||
| } |
| @@ -0,0 +1,45 @@ | ||
| #include "GameClock.h" | ||
| #include "segautils\Defs.h" | ||
| #include "segashared\CheckedMemory.h" | ||
| #include "SEGA\App.h" | ||
|
|
||
| struct GameClock_t { | ||
| long time, appTime; | ||
| bool paused; | ||
| }; | ||
|
|
||
| GameClock *gameClockCreate(){ | ||
| GameClock *out = checkedCalloc(1, sizeof(GameClock)); | ||
| return out; | ||
| } | ||
| void gameClockDestroy(GameClock *self){ | ||
| checkedFree(self); | ||
| } | ||
|
|
||
| static void _updateTime(GameClock *self){ | ||
| long newTime = (long)appGetTime(appGet()); | ||
| long elapsed = newTime - self->appTime; | ||
|
|
||
| self->time += elapsed; | ||
| self->appTime = newTime; | ||
| } | ||
|
|
||
| long gameClockGetTime(GameClock *self){ | ||
| if (!self->paused){ | ||
| _updateTime(self); | ||
| } | ||
|
|
||
| return self->time; | ||
| } | ||
| void gameClockPause(GameClock *self){ | ||
| if (!self->paused){ | ||
| _updateTime(self); | ||
| self->paused = true; | ||
| } | ||
| } | ||
| void gameClockResume(GameClock *self){ | ||
| if (self->paused){ | ||
| self->appTime = (long)appGetTime(appGet()); | ||
| self->paused = false; | ||
| } | ||
| } |
| @@ -0,0 +1,10 @@ | ||
| #pragma once | ||
|
|
||
| typedef struct GameClock_t GameClock; | ||
|
|
||
| GameClock *gameClockCreate(); | ||
| void gameClockDestroy(GameClock *self); | ||
|
|
||
| long gameClockGetTime(GameClock *self); | ||
| void gameClockPause(GameClock *self); | ||
| void gameClockResume(GameClock *self); |
| @@ -0,0 +1,8 @@ | ||
| #include "GameState.h" | ||
|
|
||
| ImpleStateMessage(GameStateUpdate) | ||
| ImpleStateMessage(GameStateHandleInput) | ||
| ImpleStateMessage(GameStateRender) | ||
|
|
||
|
|
||
|
|
| @@ -0,0 +1,12 @@ | ||
| #pragma once | ||
|
|
||
| #include "segautils\FSM.h" | ||
|
|
||
| typedef struct WorldView_t WorldView; | ||
| typedef struct Frame_t Frame; | ||
|
|
||
| DeclStateMessage(GameStateUpdate); | ||
| DeclStateMessage(GameStateHandleInput); | ||
| DeclStateMessageWithData(GameStateRender, { Frame *frame; }); | ||
|
|
||
| StateClosure gameStateCreateWorld(WorldView *view); |
| @@ -0,0 +1,90 @@ | ||
| #include "ImageLibrary.h" | ||
|
|
||
| #include "segalib\EGA.h" | ||
| #include "segautils\BitTwiddling.h" | ||
|
|
||
| typedef struct { | ||
| StringView key; | ||
| ManagedImage *value; | ||
| } iEntry; | ||
|
|
||
| #define HashTableT iEntry | ||
| #include "segautils\HashTable_Create.h" | ||
|
|
||
| typedef struct ManagedImage_t{ | ||
| ht(iEntry) *map; | ||
| StringView path; | ||
| Image *image; | ||
| size_t useCount; | ||
| }; | ||
|
|
||
| void managedImageDestroy(ManagedImage *self){ | ||
| if (self->useCount > 1){ | ||
| --self->useCount; | ||
| } | ||
| else { | ||
| iEntry entry = { self->path, self }; | ||
| htErase(iEntry)(self->map, &entry); | ||
| } | ||
| } | ||
| Image *managedImageGetImage(ManagedImage *self){ | ||
| return self->image; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| static int _iEntryCompare(iEntry *e1, iEntry *e2){ | ||
| return e1->key == e2->key; | ||
| } | ||
|
|
||
| static size_t _iEntryHash(iEntry *p){ | ||
| return hashPtr((void*)p->key); | ||
| } | ||
|
|
||
| static void _iEntryDestroy(iEntry *p){ | ||
| imageDestroy(p->value->image); | ||
| checkedFree(p->value); | ||
| } | ||
|
|
||
| typedef struct ImageLibrary_t{ | ||
| ht(iEntry) *table; | ||
| }; | ||
|
|
||
| ImageLibrary *imageLibraryCreate(){ | ||
| ImageLibrary *out = checkedCalloc(1, sizeof(ImageLibrary)); | ||
| out->table = htCreate(iEntry)(&_iEntryCompare, &_iEntryHash, &_iEntryDestroy); | ||
| return out; | ||
| } | ||
| void imageLibraryDestroy(ImageLibrary *self){ | ||
| htDestroy(iEntry)(self->table); | ||
| checkedFree(self); | ||
| } | ||
| ManagedImage *imageLibraryGetImage(ImageLibrary *self, StringView path){ | ||
| iEntry entry = { 0 }; | ||
| iEntry *found = 0; | ||
| ManagedImage *out = 0; | ||
|
|
||
| entry.key = path; | ||
| found = htFind(iEntry)(self->table, &entry); | ||
|
|
||
| if (!found){ | ||
| Image *newImage = imageDeserializeOptimized(path); | ||
|
|
||
| if (newImage){ | ||
| out = checkedCalloc(1, sizeof(ManagedImage)); | ||
| out->image = newImage; | ||
| out->map = self->table; | ||
| out->path = path; | ||
| out->useCount = 2; | ||
|
|
||
| entry.value = out; | ||
| htInsert(iEntry)(self->table, &entry); | ||
| } | ||
| } | ||
| else { | ||
| ++found->value->useCount; | ||
| out = found->value; | ||
| } | ||
|
|
||
| return out; | ||
| } |
| @@ -0,0 +1,16 @@ | ||
| #pragma once | ||
|
|
||
| #include "segashared\Strings.h" | ||
|
|
||
| typedef struct Image_t Image; | ||
|
|
||
| typedef struct ImageLibrary_t ImageLibrary; | ||
|
|
||
| typedef struct ManagedImage_t ManagedImage; | ||
|
|
||
| void managedImageDestroy(ManagedImage *self); | ||
| Image *managedImageGetImage(ManagedImage *self); | ||
|
|
||
| ImageLibrary *imageLibraryCreate(); | ||
| void imageLibraryDestroy(ImageLibrary *self); | ||
| ManagedImage *imageLibraryGetImage(ImageLibrary *self, StringView path); |
| @@ -0,0 +1,23 @@ | ||
| #pragma once | ||
|
|
||
| #include "segautils\Preprocessor.h" | ||
|
|
||
| typedef struct RenderManager_t RenderManager; | ||
| typedef struct CursorManager_t CursorManager; | ||
| typedef struct Frame_t Frame; | ||
| typedef struct WorldView_t WorldView; | ||
|
|
||
| typedef struct BTManagers_t { | ||
| RenderManager *renderManager; | ||
| CursorManager *cursorManager; | ||
| }BTManagers; | ||
|
|
||
| RenderManager *createRenderManager(WorldView *view, double *fps); | ||
| void renderManagerRender(RenderManager *self, Frame *frame); | ||
|
|
||
| CursorManager *createCursorManager(WorldView *view); | ||
| void cursorManagerCreateCursor(CursorManager *self); | ||
| void cursorManagerUpdate(CursorManager *self, int x, int y); | ||
|
|
||
|
|
||
|
|
| @@ -0,0 +1,109 @@ | ||
| #include "MeshRendering.h" | ||
| #include "segalib\EGA.h" | ||
|
|
||
| #include "segalib\Rasterizer.h" | ||
| #include "segautils\BitTwiddling.h" | ||
| #include "segautils\Matrix.h" | ||
| #include "segautils\Quaternion.h" | ||
|
|
||
| #define VectorTPart Vertex | ||
| #include "segautils\Vector_Impl.h" | ||
| #include "SEGA\App.h" | ||
| #include <math.h> | ||
|
|
||
| static FlatImage g_flatImage = { 0 }; | ||
|
|
||
| typedef struct{ | ||
| FlatImage *img; | ||
| Frame *frame; | ||
| } RenderData; | ||
|
|
||
| typedef struct{ | ||
| Int2 coords[3]; | ||
| }TexCoords; | ||
|
|
||
| static void textureShader(RenderData *r, TexCoords *data, TrianglePoint *p){ | ||
| int i = 0; | ||
| float texX = 0.0f, texY = 0.0f; | ||
| int x, y; | ||
| SuperScanLine *buff = NULL; | ||
|
|
||
| if (p->pos.x < 0 || p->pos.x >= EGA_RES_WIDTH || | ||
| p->pos.y < 0 || p->pos.y >= EGA_RES_HEIGHT){ | ||
| return; | ||
| } | ||
|
|
||
| for (i = 0; i < 3; ++i){ | ||
| texX += data->coords[i].x * p->b[i]; | ||
| texY += data->coords[i].y * p->b[i]; | ||
| } | ||
|
|
||
| x = abs((int)texX) % r->img->width; | ||
| y = abs((int)texY) % r->img->height; | ||
|
|
||
| buff = r->img->planes[0].lines + y; | ||
| if (!getBitFromArray(buff->pixels, x)){ | ||
| for (i = 0; i < EGA_PLANES; ++i){ | ||
| buff = r->img->planes[i + 1].lines + y; | ||
|
|
||
| setBitInArray(r->frame->planes[i].lines[p->pos.y].pixels, p->pos.x, getBitFromArray(buff->pixels, x)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static void pixelShader(RenderData *r, TexCoords *data, TrianglePoint *p){ | ||
| if (p->pos.x < 0 || p->pos.x >= EGA_RES_WIDTH || | ||
| p->pos.y < 0 || p->pos.y >= EGA_RES_HEIGHT){ | ||
| return; | ||
| } | ||
|
|
||
| frameRenderPoint(r->frame, p->pos.x, p->pos.y, 0); | ||
| } | ||
|
|
||
| static void buildTransform(Matrix *m, Transform t){ | ||
| Matrix m2 = quaternionToMatrix(&t.rotation); | ||
|
|
||
| matrixIdentity(m); | ||
| //matrixOrtho(m, 0.0f, EGA_RES_WIDTH, EGA_RES_HEIGHT, 0.0f, 1.0f, -1.0f); | ||
|
|
||
| matrixTranslate(m, (Float3){ (float)t.offset.x, (float)t.offset.y, (float)t.offset.z }); | ||
|
|
||
| *m = matrixMultiply(m, &m2); | ||
|
|
||
| matrixScale(m, (Float3){ (float)t.size.x, (float)t.size.y, (float)t.size.z }); | ||
| } | ||
|
|
||
| void renderMesh(vec(Vertex) *vbo, vec(size_t) *ibo, Image *tex, Transform t, Frame *frame){ | ||
| RenderData r = { .img = &g_flatImage, .frame = frame }; | ||
| size_t iCount = vecSize(size_t)(ibo); | ||
| size_t i = 0, j = 0; | ||
| PixelShader shader = { 0 }; | ||
| Vertex *v[3] = { 0 }; | ||
| Float3 vPos[3] = { 0 }; | ||
| Matrix m; | ||
|
|
||
| imageRenderToFlat(tex, r.img); | ||
|
|
||
| buildTransform(&m, t); | ||
| closureInit(PixelShader)(&shader, &r, (PixelShaderFunc)&textureShader, NULL); | ||
|
|
||
| for (i = 0; i < iCount / 3; ++i){ | ||
| Float3 n = { 0 }; | ||
| //fill out 3 vertices | ||
| for (j = 0; j < 3; ++j){ | ||
| v[j] = vecAt(Vertex)(vbo, *vecAt(size_t)(ibo, i * 3 + j)); | ||
| vPos[j] = matrixMultiplyV(&m, v[j]->coords); | ||
| } | ||
|
|
||
| //determine if vertex is facing away from the screen | ||
| n = vCross(vSubtract(vPos[1], vPos[0]), vSubtract(vPos[2], vPos[0])); | ||
|
|
||
| if (n.z < 0.0f){ | ||
| //render | ||
| TexCoords data = { .coords = { v[0]->texCoords, v[1]->texCoords, v[2]->texCoords } }; | ||
| drawTriangle(shader, &data, (Int2){ (int)vPos[0].x, (int)vPos[0].y }, | ||
| (Int2){ (int)vPos[1].x, (int)vPos[1].y }, | ||
| (Int2){ (int)vPos[2].x, (int)vPos[2].y }); | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| #pragma once | ||
|
|
||
| #include "segautils\Vector.h" | ||
| #include "segautils\StandardVectors.h" | ||
| #include "segautils\Quaternion.h" | ||
|
|
||
| typedef struct{ | ||
| Float3 coords; | ||
| Int2 texCoords; | ||
| }Vertex; | ||
|
|
||
| #define VectorTPart Vertex | ||
| #include "segautils\Vector_Decl.h" | ||
|
|
||
| typedef struct{ | ||
| Int3 size, offset; | ||
| Quaternion rotation; | ||
| } Transform; | ||
|
|
||
| typedef struct Image_t Image; | ||
| typedef struct Frame_t Frame; | ||
|
|
||
| void renderMesh(vec(Vertex) *vbo, vec(size_t) *ibo, Image *tex, Transform t, Frame *frame); |
| @@ -0,0 +1,298 @@ | ||
| #include "Managers.h" | ||
| #include "ImageLibrary.h" | ||
|
|
||
| #include "Entities\Entities.h" | ||
|
|
||
| #include "CoreComponents.h" | ||
| #include "segashared\CheckedMemory.h" | ||
| #include "segalib\EGA.h" | ||
| #include "MeshRendering.h" | ||
| #include "WorldView.h" | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| struct RenderManager_t{ | ||
| Manager m; | ||
| WorldView *view; | ||
| FontFactory *fontFactory; | ||
| double *fps; | ||
|
|
||
| vec(EntityPtr) *layers[LayerCount]; | ||
| }; | ||
|
|
||
| typedef struct{ | ||
| bool hasImage; | ||
| bool hasMesh; | ||
| bool hasRect; | ||
| bool hasPolygon; | ||
| bool hasText; | ||
|
|
||
| ManagedImage *img; | ||
| StringView filename; | ||
| }TRenderComponent; | ||
|
|
||
| static void _updateManagedImage(RenderManager *self, TRenderComponent *trc, ImageComponent *ic){ | ||
| if (trc->img && trc->filename != ic->filename){ | ||
| //image has changed | ||
| managedImageDestroy(trc->img); | ||
| trc->filename = ic->filename; | ||
| trc->img = imageLibraryGetImage(self->view->imageLibrary, trc->filename); | ||
| } | ||
| else { | ||
| //new image | ||
| trc->filename = ic->filename; | ||
| trc->img = imageLibraryGetImage(self->view->imageLibrary, trc->filename); | ||
| } | ||
| } | ||
|
|
||
| static bool _buildTRenderComponent(RenderManager *self, TRenderComponent *trc, Entity *e){ | ||
| bool success = false; | ||
| ImageComponent *ic = entityGet(ImageComponent)(e); | ||
|
|
||
| trc->hasImage = ic != NULL; | ||
|
|
||
| if (ic){ | ||
| _updateManagedImage(self, trc, ic); | ||
| success = true; | ||
| } | ||
|
|
||
| trc->hasRect = entityGet(RectangleComponent)(e) != NULL; | ||
| if (trc->hasRect){ success = true; } | ||
|
|
||
| trc->hasPolygon = entityGet(PolygonComponent)(e) != NULL; | ||
| if (trc->hasPolygon){ success = true; } | ||
|
|
||
| trc->hasText = entityGet(TextComponent)(e) != NULL; | ||
| if (trc->hasText){ success = true; } | ||
|
|
||
| trc->hasMesh = entityGet(MeshComponent)(e) != NULL; | ||
| if (trc->hasMesh){ success = true; } | ||
|
|
||
| return success; | ||
| } | ||
|
|
||
| static void TRenderComponentDestroy(TRenderComponent *self){ | ||
| if (self->img){ | ||
| managedImageDestroy(self->img); | ||
| } | ||
| } | ||
|
|
||
| #define COMP_DESTROY_FUNC TRenderComponentDestroy | ||
| #define TComponentT TRenderComponent | ||
| #include "Entities\ComponentDeclTransient.h" | ||
|
|
||
| void _initLayers(RenderManager *self){ | ||
| vec(EntityPtr) **first = self->layers; | ||
| vec(EntityPtr) **last = first + LayerCount; | ||
|
|
||
| while (first != last){ (*first++) = vecCreate(EntityPtr)(NULL); } | ||
| } | ||
|
|
||
| void _destroyLayers(RenderManager *self){ | ||
| vec(EntityPtr) **first = self->layers; | ||
| vec(EntityPtr) **last = first + LayerCount; | ||
|
|
||
| while (first != last){ vecDestroy(EntityPtr)(*first++); } | ||
| } | ||
|
|
||
| static void _imageComponentUpdate(RenderManager *self, Entity *e, ImageComponent *oldIC){ | ||
| ImageComponent *ic = entityGet(ImageComponent)(e); | ||
| TRenderComponent *trc = entityGet(TRenderComponent)(e); | ||
| if (trc){ | ||
| _updateManagedImage(self, trc, ic); | ||
| } | ||
| } | ||
|
|
||
| static void _registerUpdateDelegate(RenderManager *self, EntitySystem *system){ | ||
| ComponentUpdate update; | ||
|
|
||
| closureInit(ComponentUpdate)(&update, self, (ComponentUpdateFunc)&_imageComponentUpdate, NULL); | ||
| compRegisterUpdateDelegate(ImageComponent)(system, update); | ||
| } | ||
|
|
||
| ImplManagerVTable(RenderManager) | ||
|
|
||
| RenderManager *createRenderManager(WorldView *view, double *fps){ | ||
| RenderManager *out = checkedCalloc(1, sizeof(RenderManager)); | ||
| Image *fontImage = imageDeserializeOptimized("assets/img/font.ega"); | ||
| out->view = view; | ||
| out->m.vTable = CreateManagerVTable(RenderManager); | ||
| out->fontFactory = fontFactoryCreate(fontImage); | ||
| out->fps = fps; | ||
| _initLayers(out); | ||
|
|
||
| _registerUpdateDelegate(out, view->entitySystem); | ||
|
|
||
| imageDestroy(fontImage); | ||
| return out; | ||
| } | ||
|
|
||
| void _destroy(RenderManager *self){ | ||
| fontFactoryDestroy(self->fontFactory); | ||
| _destroyLayers(self); | ||
| checkedFree(self); | ||
| } | ||
|
|
||
| void _onDestroy(RenderManager *self, Entity *e){} | ||
|
|
||
| void _onUpdate(RenderManager *self, Entity *e){ | ||
| TRenderComponent *trc = entityGet(TRenderComponent)(e); | ||
| TRenderComponent newtrc = { 0 }; | ||
|
|
||
| if (!trc){//no trc | ||
| if (_buildTRenderComponent(self, &newtrc, e)){//we were able to generate one | ||
| entityAdd(TRenderComponent)(e, &newtrc);//add it | ||
| } | ||
| } | ||
| else{//trc present | ||
| if (!_buildTRenderComponent(self, trc, e)){//on refresh, its no longer rendered | ||
| entityRemove(TRenderComponent)(e);//remove it | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void _clearLayers(RenderManager *self){ | ||
| vec(EntityPtr) **first = self->layers; | ||
| vec(EntityPtr) **last = first + LayerCount; | ||
|
|
||
| while (first != last){ vecClear(EntityPtr)(*first++); } | ||
| } | ||
|
|
||
| void _addToLayers(RenderManager *self, Entity* e){ | ||
| Layer layer = 0; | ||
| LayerComponent *lc = entityGet(LayerComponent)(e); | ||
|
|
||
| if (lc){ | ||
| layer = lc->layer; | ||
| } | ||
|
|
||
| if (layer < LayerCount){ | ||
| vecPushBack(EntityPtr)(self->layers[layer], &e); | ||
| } | ||
| } | ||
|
|
||
| void _renderMeshEntity(Entity *e, Frame *frame, MeshComponent *mc, short x, short y, Image *img){ | ||
| Transform t = { | ||
| .size = (Int3){ mc->size, mc->size, mc->size }, | ||
| .offset = (Int3){ x, y, 0 }, | ||
| .rotation = quaternionFromAxisAngle(mc->rotNormal, mc->angle) | ||
| }; | ||
| renderMesh(mc->vbo, mc->ibo, img, t, frame); | ||
| } | ||
|
|
||
| void _renderPolygon(Frame *frame, vec(Int2) *pList, byte color, bool open){ | ||
| if (!vecIsEmpty(Int2)(pList)){ | ||
| Int2 *begin = vecBegin(Int2)(pList); | ||
| Int2 *end = vecEnd(Int2)(pList); | ||
| while (begin != end - 1){ | ||
| Int2 p0 = *begin++; | ||
| Int2 p1 = *begin; | ||
|
|
||
| frameRenderLine(frame, p0.x, p0.y, p1.x, p1.y, color); | ||
| } | ||
|
|
||
| if(!open && vecSize(Int2)(pList) >= 2) { | ||
| Int2 p0 = *vecBack(Int2)(pList); | ||
| Int2 p1 = *vecBegin(Int2)(pList); | ||
|
|
||
| frameRenderLine(frame, p0.x, p0.y, p1.x, p1.y, color); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void _renderEntity(RenderManager *self, Entity *e, Frame *frame){ | ||
| TRenderComponent *trc = entityGet(TRenderComponent)(e); | ||
| PositionComponent *pc = entityGet(PositionComponent)(e); | ||
| VisibilityComponent *vc = entityGet(VisibilityComponent)(e); | ||
| int x = 0, y = 0; | ||
|
|
||
| if (vc && !vc->shown){ | ||
| return; | ||
| } | ||
|
|
||
| if (pc){ | ||
| x = pc->x; | ||
| y = pc->y; | ||
| } | ||
|
|
||
| //render rect | ||
| if (trc->hasRect){ | ||
| RectangleComponent *rc = entityGet(RectangleComponent)(e); | ||
| SizeComponent *sc = entityGet(SizeComponent)(e); | ||
| if (rc && sc){ | ||
| frameRenderRect(frame, x, y, x + sc->x, y + sc->y, rc->color); | ||
| } | ||
| } | ||
|
|
||
| //render image (or mesh) | ||
| if (trc->hasImage && trc->img){ | ||
| Image *img = managedImageGetImage(trc->img); | ||
|
|
||
| if (trc->hasMesh){ | ||
| MeshComponent *mc = entityGet(MeshComponent)(e); | ||
| if (mc){ _renderMeshEntity(e, frame, mc, x, y, img); } | ||
| } | ||
| else{ | ||
| ImageComponent *ic = entityGet(ImageComponent)(e); | ||
| if (ic->partial){ | ||
| frameRenderImagePartial(frame, x, y, img, ic->x, ic->y, ic->width, ic->height); | ||
| } | ||
| else{ | ||
| frameRenderImage(frame, x, y, img); | ||
| } | ||
|
|
||
| } | ||
| } | ||
|
|
||
| //polygons | ||
| if (trc->hasPolygon){ | ||
| PolygonComponent *pc = entityGet(PolygonComponent)(e); | ||
| _renderPolygon(frame, pc->pList, pc->color, pc->open); | ||
| } | ||
|
|
||
| //text | ||
| if (trc->hasText){ | ||
| TextComponent *tc = entityGet(TextComponent)(e); | ||
| frameRenderText(frame, c_str(tc->text), tc->x, tc->y, | ||
| fontFactoryGetFont(self->fontFactory, tc->bg, tc->fg)); | ||
| } | ||
| } | ||
|
|
||
| void _renderLayer(RenderManager *self, vec(EntityPtr) *layer, Frame *frame){ | ||
| vecForEach(EntityPtr, e, layer, { | ||
| _renderEntity(self, *e, frame); | ||
| }); | ||
| } | ||
|
|
||
| void _renderLayers(RenderManager *self, Frame *frame){ | ||
| vec(EntityPtr) **first = self->layers; | ||
| vec(EntityPtr) **last = first + LayerCount; | ||
|
|
||
| while (first != last){ _renderLayer(self, *first++, frame); } | ||
| } | ||
|
|
||
|
|
||
| void _renderFramerate(Frame *frame, Font *font, double d){ | ||
| static char buffer[256] = { 0 }; | ||
| short y = 0; | ||
| short x; | ||
| sprintf(buffer, "FPS: %.2f", d); | ||
|
|
||
| x = EGA_TEXT_RES_WIDTH - strlen(buffer); | ||
| frameRenderText(frame, buffer, x, y, font); | ||
| } | ||
|
|
||
| void renderManagerRender(RenderManager *self, Frame *frame){ | ||
| frameClear(frame, 0); | ||
|
|
||
| _clearLayers(self); | ||
|
|
||
| COMPONENT_QUERY(self->view->entitySystem, TRenderComponent, trc, { | ||
| Entity *e = componentGetParent(trc, self->view->entitySystem); | ||
| _addToLayers(self, e); | ||
| }); | ||
|
|
||
| _renderLayers(self, frame); | ||
|
|
||
| _renderFramerate(frame, fontFactoryGetFont(self->fontFactory, 7, 0), *self->fps); | ||
| } |
| @@ -0,0 +1,77 @@ | ||
| #include "WorldView.h" | ||
| #include "Managers.h" | ||
| #include "Entities\Entities.h" | ||
| #include "ImageLibrary.h" | ||
| #include "segalib\EGA.h" | ||
|
|
||
| #include "GameState.h" | ||
| #include "SEGA\Input.h" | ||
| #include "SEGA\App.h" | ||
| #include "segashared\CheckedMemory.h" | ||
|
|
||
| #include "CoreComponents.h" | ||
| #include "segashared\Strings.h" | ||
| #include "GameClock.h" | ||
|
|
||
| typedef struct { | ||
| WorldView *view; | ||
| }WorldState; | ||
|
|
||
| static void _boardStateDestroy(WorldState *self){ | ||
| checkedFree(self); | ||
| } | ||
|
|
||
| static void _boardUpdate(WorldState*, GameStateUpdate*); | ||
| static void _boardHandleInput(WorldState*, GameStateHandleInput*); | ||
| static void _boardRender(WorldState*, GameStateRender*); | ||
|
|
||
| static void _board(WorldState *state, Type *t, Message m){ | ||
| if (t == GetRTTI(GameStateUpdate)){ _boardUpdate(state, m); } | ||
| else if (t == GetRTTI(GameStateHandleInput)){ _boardHandleInput(state, m); } | ||
| else if (t == GetRTTI(GameStateRender)){ _boardRender(state, m); } | ||
| } | ||
|
|
||
|
|
||
| void _boardUpdate(WorldState *state, GameStateUpdate *m){ | ||
| BTManagers *managers = state->view->managers; | ||
| Mouse *mouse = appGetMouse(appGet()); | ||
| Int2 mousePos = mouseGetPosition(mouse); | ||
|
|
||
| cursorManagerUpdate(managers->cursorManager, mousePos.x, mousePos.y); | ||
| } | ||
|
|
||
| static void _handleKeyboard(WorldState *state){ | ||
| BTManagers *managers = state->view->managers; | ||
| Keyboard *k = appGetKeyboard(appGet()); | ||
| KeyboardEvent e = { 0 }; | ||
| while (keyboardPopEvent(k, &e)){ | ||
| } | ||
| } | ||
|
|
||
| static void _handleMouse(WorldState *state){ | ||
| BTManagers *managers = state->view->managers; | ||
| Mouse *mouse = appGetMouse(appGet()); | ||
| Keyboard *k = appGetKeyboard(appGet()); | ||
| MouseEvent event = { 0 }; | ||
| while (mousePopEvent(mouse, &event)){ | ||
| } | ||
| } | ||
|
|
||
| void _boardHandleInput(WorldState *state, GameStateHandleInput *m){ | ||
| _handleKeyboard(state); | ||
| _handleMouse(state); | ||
| } | ||
|
|
||
| void _boardRender(WorldState *state, GameStateRender *m){ | ||
| renderManagerRender(state->view->managers->renderManager, m->frame); | ||
| } | ||
|
|
||
| StateClosure gameStateCreateWorld(WorldView *view){ | ||
| StateClosure out; | ||
| WorldState *state = checkedCalloc(1, sizeof(WorldState)); | ||
|
|
||
| state->view = view; | ||
| closureInit(StateClosure)(&out, state, (StateClosureFunc)&_board, &_boardStateDestroy); | ||
|
|
||
| return out; | ||
| } |
| @@ -0,0 +1,15 @@ | ||
| #pragma once | ||
|
|
||
| typedef struct BTManagers_t BTManagers; | ||
| typedef struct EntitySystem_t EntitySystem; | ||
| typedef struct ImageLibrary_t ImageLibrary; | ||
| typedef struct FSM_t FSM; | ||
| typedef struct GameClock_t GameClock; | ||
|
|
||
| typedef struct WorldView_t { | ||
| BTManagers *managers; | ||
| EntitySystem *entitySystem; | ||
| ImageLibrary *imageLibrary; | ||
| FSM *gameState; | ||
| GameClock *gameClock; | ||
| }WorldView; |
| @@ -22,7 +22,7 @@ | ||
| typedef struct { | ||
| VirtualApp vApp; | ||
| AppData data; | ||
| ShiftManagers managers; | ||
| EntitySystem *entitySystem; | ||
| ImageLibrary *imageLibrary; | ||
| FSM *gameState; | ||