diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b7d8e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/copy/ +/build/ +.sconsign* +.pydevproject +*.kate-swp +*.kdev4 diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..cf81332 --- /dev/null +++ b/SConstruct @@ -0,0 +1,3 @@ +build_dir = ARGUMENTS.get('build_dir', 'build') +VariantDir(build_dir, 'src', duplicate = 0) +SConscript(build_dir + '/SConstruct') diff --git a/heliantus/SConstruct b/heliantus/SConstruct new file mode 100644 index 0000000..51fc8ab --- /dev/null +++ b/heliantus/SConstruct @@ -0,0 +1,30 @@ + +env = Environment() + + +# config + +libs = [] + + +# compute build options + +flags = ' -O0 -g -Wall -fmessage-length=0 ' + + +# files lists + +target = 'cblocks' + +sources = [ + 'main.c' ] + + +# build + +env.ParseConfig('pkg-config --cflags --libs ' + ' '.join(libs)) + +env.Program( + target = target, + source = sources, + parse_flags = flags ) diff --git a/heliantus/common.h b/heliantus/common.h new file mode 100644 index 0000000..692b93c --- /dev/null +++ b/heliantus/common.h @@ -0,0 +1,18 @@ +#ifndef HELI_COMMON_H +#define HELI_COMMON_H + + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +int randomNumber(int min, int max); +double randomFloat(); + + +#endif diff --git a/heliantus/drawing.h b/heliantus/drawing.h new file mode 100644 index 0000000..7dfff33 --- /dev/null +++ b/heliantus/drawing.h @@ -0,0 +1,44 @@ +#ifndef HELI_DRAWING_H +#define HELI_DRAWING_H + + +#include "common.h" + +enum HAlign { + HALIGN_LEFT, + HALIGN_CENTER, + HALIGN_RIGHT +}; + +enum VAlign { + VALIGN_TOP, + VALIGN_CENTER, + VALIGN_BOTTOM +}; + + +void background(char *color); +void fill(char *color); +void noFill(); +void stroke(char *color); +void noStroke(); +void strokeWeight(double weight); +char* rgb(double r, double g, double b); +char* rgba(double r, double g, double b, double a); +void rect(double x, double y, double width, double height); +void ellipse(double x, double y, double width, double height); +void text(char *text, double x, double y); +void textEx(char *text, double x, double y, double x2, double y2); +void textAlign(HAlign hor, VAlign vert); +void textFont(char *font); +void textSize(double size); +void arc(double x, double y, double w, double h, double start, double stop); +void line(double x1, double y1, double x1, double y1); +void point(double x, double y); +void regularPolygon(double x, double y, int sides, double size); +void moveTo(double x, double y); +void lineTo(double x, double y); + + +#endif + diff --git a/heliantus/group.h b/heliantus/group.h new file mode 100644 index 0000000..fa8a405 --- /dev/null +++ b/heliantus/group.h @@ -0,0 +1,58 @@ +#ifndef HELI_GROUP_H +#define HELI_GROUP_H + + +#include "sprite.h" + + +typedef struct _Group *Group; + + +Group createGroup(); +void gorupDestroy(Group group); + +void groupAdd(Group group, Sprite sprite); +void groupRemove(Group group, Sprite sprite); +void groupClear(Group group); +int groupContains(Group group, Sprite sprite); +int groupGetCount(Group group); +Sprite groupGet(Group group, int i); + +int groupGetColliderId(Group group); + +int groupIsTouching(Group group, int colliderId); + +int groupBounce(Group group, int colliderId); +int groupBounceOff(Group group, int colliderId); +int groupCollide(Group group, int colliderId); +int groupDisplace(Group group, int colliderId); +int groupOverlap(Group group, int colliderId); + +double groupGetMinDepth(Group group); +double groupGetMaxDepth(Group group); + +void groupDestroyEach(Group group); +void groupSetVisibleEach(Group group, int visible); +void groupSetWidthEach(Group group, double width); +void groupSetHeightEach(Group group, double height); +void groupSetDepthEach(Group group, double depth); +void groupSetVelocityXEach(Group group, double velocityX); +void groupSetVelocityYEach(Group group, double velocityY); +void groupSetVelocityEach(Group group, double x, double y); +void groupSetLifetimeEach(Group group, double lifetime); +void groupSetRotateToDirectionEach(Group group, int rotateToDirection); +void groupSetRotationEach(Group group, double rotation); +void groupSetRotationSpeedEach(Group group, double rotationSpeed); +void groupSetScaleEach(Group group, double scale); +void groupSetMirrorXEach(Group group, int mirrorX); +void groupSetMirrorYEach(Group group, int mirrorY); +void groupPointToEach(Group group, double x, double y); +void groupSetSpeedAndDirectionEach(Group group, double speed, double angle); +void groupSetAnimationEach(Group group, char *label); +void groupSetColorEach(Group group, char *color); +void groupSetColliderEach(Group group, Collider type, double xOffset, double yOffset); +void groupSetColliderEachEx(Group group, Collider type, double xOffset, double yOffset, + double widthOrRadius, double height, double rotationOffset); + + +#endif diff --git a/heliantus/main.c b/heliantus/main.c new file mode 100644 index 0000000..1a77d87 --- /dev/null +++ b/heliantus/main.c @@ -0,0 +1,15 @@ + +#include + +void init() { +} + +void draw() { +} + +int main() { + worldSetInit(&init); + worldSetDraw(&draw); + worldRun(); + return 0; +} diff --git a/heliantus/private.c b/heliantus/private.c new file mode 100644 index 0000000..5175c9a --- /dev/null +++ b/heliantus/private.c @@ -0,0 +1,114 @@ + +#include "private.h" + + + +static char* heliStringCopy(char *x) { + int len = strlen(x) + 1; + char *cp = malloc(len + 1); + memcpy(cp, x, len); + return cp; +} + +static void heliLowercase(char *x) + { while(*x) *x = tolower(*x); } + + + +int heliArrayInit(HeliArray *a) { + a->items = NULL; + a->count = a->allocated = 0; +} + +void heliArrayClear(HeliArray *a, int freeData) { + if (freeData) + for(int i = 0; i < a->count; ++i) + free(a->items[i]); + a->count = 0; +} + +int heliArrayDestroy(HeliArray *a, int freeData) { + heliArrayClear(a, freeData); + free(a->items); + a->items = NULL; + a->count = a->allocated = 0; +} + +void* heliArrayGet(HeliArray *a, int i) + { return i >= 0 && i < a->count ? a->items[i] : NULL; } + +void heliArrayInsert(HeliArray *a, int i, void *item) { + if (i < 0 || i > a->count) + i = a->count; + if (a->allocated < a->count + 1) { + a->allocated += a->allocated/4 + 32; + a->items = realloc(a->items, a->allocated); + } + if (i < a->count) + memmove(&a->items[i+1], &a->items[i], (a->count-i)*sizeof(a->items[0])); + ++a->count; + a->items[i] = item; +} + +void heliArrayAppend(HeliArray *a, void *data) + { heliArrayInsert(a, a->count, data); } + +void heliArrayRemove(HeliArray *a, int i, int freeData) { + if (i < 0 || i >= a->count) + return; + if (freeData) free(a->items[i]); + memmove(&a->items[i], &a->items[i+1], (a->count-i-1)*sizeof(a->items[0])); + --a->count; +} + +int heliStringsetFind(HeliArray *a, char *x, int *gtOrEqIndex) { + for(int i = 0; i < a->count; ++i) { + int cmp = strcmp((char*)a->items[i], x); + if (cmp < 0) continue; + if (gtOrEqIndex) *gtOrEqIndex = i; + return cmp == 0; + } + if (gtOrEqIndex) *gtOrEqIndex = a->count; + return 0; +} + +int heliStringsetGet(HeliArray *a, char *x) + { return heliStringsetFind(a, x, NULL); } + +void heliStringsetAdd(HeliArray *a, char *x) { + int i; + if (heliStringsetFind(a, x, &i)) return; + heliArrayInsert(a, i, heliStringCopy(x)); +} + +void heliStringsetRemove(HeliArray *a, char *x) { + int i; + if (!heliStringsetFind(a, x, &i)) return; + heliArrayRemove(a, i, TRUE); +} + + + +int heliCheckCollision(HeliCollider *a, HeliCollider *b, double *normX, double *normY) { + // corner with side + // corner with circle + // circle with circle + #warning "TODO: heliCheckCollision: not implemented yet" + return FALSE; +} + +int heliPointCollision(HeliCollider *c, double x, double y) { + x -= c->x; + y -= c->y; + if (c->type == COLLIDER_CIRCLE) { + return x*x + y*y <= c->radius*c->radius; + } else + if (c->type == COLLIDER_RECTANGLE) { + double a = c->rotation/180.0*M_PI; + double sn = sin(a); + double cn = cos(a); + return fabs(x*cn - y*sn) <= c->width*0.5 + && fabs(x*sn + y*cn) <= c->height*0.5; + } + return FALSE; +} diff --git a/heliantus/private.h b/heliantus/private.h new file mode 100644 index 0000000..62734c3 --- /dev/null +++ b/heliantus/private.h @@ -0,0 +1,59 @@ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "sprite.h" + + +// sprite + +void heliUpdateSprites(); + + +// string + +char* heliStringCopy(char *x); +void heliLowercase(char *x); + + +// pointer array + +typedef struct _HeliArray { + void **items; + int count; + int allocated; +} HeliArray; + +int heliArrayInit(HeliArray *a); +void heliArrayClear(HeliArray *a, int freeData); +int heliArrayDestroy(HeliArray *a, int freeData); +void* heliArrayGet(HeliArray *a, int i); +void heliArrayInsert(HeliArray *a, int i, void *item); +void heliArrayAppend(HeliArray *a, void *item); +void heliArrayRemove(HeliArray *a, int i, int freeData); + +int heliStringsetFind(HeliArray *a, char *x, int *gtOrEqIndex); +int heliStringsetGet(HeliArray *a, char *x); +void heliStringsetAdd(HeliArray *a, char *x); +void heliStringsetRemove(HeliArray *a, char *x); + + +// collider + +typedef struct _HeliCollider { + Collider type; + double x; + double y; + double radius; + double width; + double height; + double rotation; +} HeliCollider; + +int heliCheckCollision(HeliCollider *a, HeliCollider *b, double *normX, double *normY); +int heliPointCollision(HeliCollider *c, double x, double y); + diff --git a/heliantus/sprite.c b/heliantus/sprite.c new file mode 100644 index 0000000..69c7dd9 --- /dev/null +++ b/heliantus/sprite.c @@ -0,0 +1,109 @@ + +#include "private.h" + +#include "sprite.h" +#include "world.h" + +struct _Sprite { + double x; + double y; + double rotation; + double width; + double height; + double scale; + + double vx; + double vy; + double rotationSpeed; + + HeliCollider collider; + int colliderId; + double bounciness; + + int rotateToDirection; + int mirrorX; + int mirrorY; + double depth; + double lifeTime; + int debug; + + double color[4]; + double tint[4]; + + int playing; + int frame; + + HeliArray images; +}; + +static HeliArray sprites; +static HeliArray sortedSprites; + + +static void prepareCollider(Sprite sprite, HeliCollider *collider) { + #error +} + + + +int worldGetSpriteCount() + { return sprites.count; } + +Sprite worldGetSprite(int i) { + { return (Sprite)heliArrayGet(&sprites, i); } + +void drawSprites() { + // copy + for(int i = 0; i < sprites.count; ++i) + heliArrayAppend(&sortedSprites, sprites.items[i]); + + // sort + int found = TRUE; + while(found) { + found = FALSE; + for(int i = 1; i < sortedSprites.count; ++i) { + if (((Sprite)sortedSprites.items[i-1])->depth < ((Sprite)sortedSprites.items[i])->depth) { + void *x = sortedSprites.items[i]; + sortedSprites.items[i] = sortedSprites.items[i-1]; + sortedSprites.items[i-1] = x; + found = TRUE; + } + } + } + + // draw + for(int i = 1; i < sortedSprites.count; ++i) { + Sprite s = (Sprite)(sortedSprites.items[i]); + #error + } + + // clear + heliArrayClear(sortedSprites, FALSE); +} + +int mouseIsOver(Sprite sprite) { + HeliCollider collider; + prepareCollider(sprite, &collider); + heliPointCollision(&collider, mouseX(), mouseY()); +} + +void heliUpdateSprites(double dt) { + for(int i = 1; i < sprites.count; ++i) { + Sprite s = (Sprite)(sprites.items[i]); + s->x += s->vx*dt; + s->y += s->vy*dt; + s->rotation += s->rotationSpeed*dt; + if (s->playing) { + ++s->frame; + if (s->frames.count <= 0) { + s->frame = 0; + } else + if (s->frame > s->frames.count) { + s->frame %= s->frames.count; + } else + if (s->frame < 0) { + s->frame = 0; + } + } + } +} diff --git a/heliantus/sprite.h b/heliantus/sprite.h new file mode 100644 index 0000000..8b8e45f --- /dev/null +++ b/heliantus/sprite.h @@ -0,0 +1,103 @@ +#ifndef HELI_SPRITE_H +#define HELI_SPRITE_H + + +#include "common.h" + +typedef struct _Sprite *Sprite; + + +typedef enum _Collider { + COLLIDER_RECTANGLE, + COLLIDER_CIRCLE +} Collider; + +Sprite createSprite(double x, double y); +Sprite createSpriteEx(double x, double y, double width, double height); + +void spriteDestroy(Sprite sprite); + +double spriteGetX(Sprite sprite); +void spriteSetX(Sprite sprite, double x); + +double spriteGetY(Sprite sprite); +void spriteSetY(Sprite sprite, double y); + +double spriteGetVelocityX(Sprite sprite); +void spriteSetVelocityX(Sprite sprite, double x); + +double spriteGetVelocityY(Sprite sprite); +void spriteSetVelocityY(Sprite sprite, double y); + +double spriteGetScale(Sprite sprite); +void spriteSetScale(Sprite sprite, double scale); + +double spriteGetWidth(Sprite sprite); +void spriteSetWidth(Sprite sprite, double width); + +double spriteGetHeight(Sprite sprite); +void spriteSetHeight(Sprite sprite, double height); + +int spriteGetRotateToDirection(Sprite sprite); +void spriteSetRotateToDirection(Sprite sprite, int rotateToDirection); + +double spriteGetRotation(Sprite sprite); +void spriteSetRotation(Sprite sprite, double rotation); + +double spriteGetRotationSpeed(Sprite sprite); +void spriteSetRotationSpeed(Sprite sprite, double rotationSpeed); + +int spriteGetMirrorX(Sprite sprite); +void spriteSetMirrorX(Sprite sprite, int mirrorX); + +int spriteGetMirrorY(Sprite sprite); +void spriteSetMirrorY(Sprite sprite, int mirrorY); + +double spriteGetDepth(Sprite sprite); +void spriteSetDepth(Sprite sprite, double depth); + +double spriteGetLifeTime(Sprite sprite); +void spriteSetLifeTime(Sprite sprite, double lifeTime); + +int spriteGetDebug(Sprite sprite); +void spriteSetDebug(Sprite sprite, int debug); + +int spriteGetColliderId(Sprite sprite); + +int spriteIsTouching(Sprite sprite, int colliderId); + +int spriteBounce(Sprite sprite, int colliderId); +int spriteBounceOff(Sprite sprite, int colliderId); +int spriteCollide(Sprite sprite, int colliderId); +int spriteDisplace(Sprite sprite, int colliderId); +int spriteOverlap(Sprite sprite, int colliderId); + +double spriteGetBounciness(Sprite sprite); +void spriteSetBounciness(Sprite sprite, double bounciness); + +void spriteSetCollider(Sprite sprite, Collider type, double xOffset, double yOffset); +void spriteSetColliderEx(Sprite sprite, Collider type, double xOffset, double yOffset, + double widthOrRadius, double height, double rotationOffset); + +void spriteSetAnimation(Sprite sprite, char *label); +void spritePlay(Sprite sprite); +void spritePause(Sprite sprite); +void spriteNextFrame(Sprite sprite); +void spriteSetFrame(Sprite sprite, int frame); +void spriteSetShapeColor(Sprite sprite, char *color); +void spriteSetTint(Sprite sprite, char *color); + +void spriteSetVelocityXY(Sprite sprite, double x, double y); +void spriteSetSpeedAndDirection(Sprite sprite, double speed, double angle); +double spriteGetSpeed(Sprite sprite); +double spriteGetDirection(Sprite sprite); +void spritePointTo(Sprite sprite, double x, double y); + +double spriteGetScaledWidth(Sprite sprite); +double spriteGetScaledHeight(Sprite sprite); + + +void createEdgeSprites(); + + +#endif diff --git a/heliantus/world.c b/heliantus/world.c new file mode 100644 index 0000000..d9908d2 --- /dev/null +++ b/heliantus/world.c @@ -0,0 +1,283 @@ + +#include +#include +#include + +#include "private.h" + +#include "world.h" + + +cairo_t *heliCairo; + + +static GtkWidget *window; + +static int started; +static int stopped; +static unsigned long long frameCount; +static gint64 startTime; +static gint64 currentTime; +static guint timerInterval; + +static Callback initCallback; +static Callback drawCallback; + +static int width; +static int height; +static double frameRate = 30; + +static int cameraEnabled; +static double cameraX; +static double cameraY; +static double cameraZoom = 1; + +static HeliArray keysPressed; +static HeliArray keysPressedInFrame; +static HeliArray keysReleasedInFrame; +static HeliArray buttonsPressed; +static HeliArray buttonsPressedInFrame; +static HeliArray buttonsReleasedInFrame; + +static int mouseMovedInFrame; +static double _mouseX; +static double _mouseY; + +static char* buttonNames[] = { + "left", + "middle", + "right" }; +static int buttonsCount = (int)(sizeof(buttonNames)/sizeof(*buttonNames)); + + + +void playSound(char *path, int loop) { + #warning "TODO: playSound: not implemented yet" +} + +void stopSound(char *path) { + #warning "TODO: stopSound: not implemented yet" +} + +int keyDown(char *code) + { return heliStringsetGet(&keysPressed, code); } +int keyWentDown(char *code); + { return heliStringsetGet(&keysPressedInFrame, code); } +int keyWentUp(char *code); + { return heliStringsetGet(&keysReleasedInFrame, code); } + +int mouseDidMove() + { return mouseMovedInFrame; } +int mouseDown(char *code) + { return heliStringsetGet(&buttonsPressed, code); } +int mouseWentDown(char *code) + { return heliStringsetGet(&buttonsPressedInFrame, code); } +int mouseWentUp(char *code) + { return heliStringsetGet(&buttonsReleasedInFrame, code); } +double mouseX() + { return _mouseX; } +double mouseY() + { return _mouseY; } + +int mousePressedOver(Sprite sprite) + { return buttonsPressed.count && int mouseIsOver(sprite); } + +int worldGetWidth() + { return width; } +void worldSetWidth(int w) { + width = w; + if (started) gtk_widget_set_size_request(window, width, height); +} + +int worldGetHeight(); + { return height; } +void worldSetHeight(int h) { + height = h; + if (started) gtk_widget_set_size_request(window, width, height); +} + +double worldGetFrameRate() + { return frameRate; } +void worldSetFrameRate(double frameRate) { + if (!(frameRate > 1)) frameRate = 1; + if (!(frameRate < 100)) frameRate = 100; +} + +int worldGetFrameCount() + { return (int)frameCount; } +double worldGetSeconds() + { return started ? (currentTime - startTime)*1e-6 : 0.0; } + +void worldSetInit(Callback init) + { initCallback = init; } +void worldSetDraw(Callback draw) + { drawCallback = draw; } +void worldStop() + { if (started) stopped = TRUE; } + + +void cameraOn() + { cameraEnabled = TRUE; } +void cameraOff() + { cameraEnabled = FALSE; } +int cameraIsActive() + { return cameraEnabled; } + +double cameraMouseX() + { return _mouseX/cameraZoom + cameraX; } +double cameraMouseY() + { return _mouseY/cameraZoom + cameraY; } + +double cameraGetX() + { return cameraX; } +void cameraSetX(double x) + { cameraX = x; } + +double cameraGetY() + { return cameraY; } +void cameraSetY(double y) + { cameraY = y; } + +double cameraGetZoom() + { return cameraZoom; } +void cameraSetZoom(double x) + { cameraZoom = x > 1e-6 ? x : 1e-6; } + + +static gboolean timeout(gpointer data G_GNUC_UNUSED) { + gtk_widget_queue_draw(window); + if (stopped) { + gtk_window_close(GTK_WINDOW(window)); + return FALSE; + } + guint interval = (guint)round(1000/frameRate); + if (interval != timerInterval) { + timerInterval = interval; + g_timeout_add(timerInterval, timeout, NULL); + return FALSE; + } + return TRUE; +} + +static gboolean draw(GtkWidget *widget G_GNUC_UNUSED, cairo_t *cr, gpointer data G_GNUC_UNUSED) { + guint64 newTime = g_get_monotonic_time(); + heliCairo = cr; + + if (!frameCount) { + startTime = currentTime = newTime; + if (initCallback) initCallback(); + if (drawCallback) drawCallback(); + heliArrayClear(&keysPressedInFrame, TRUE); + heliArrayClear(&keysReleasedInFrame, TRUE); + heliArrayClear(&buttonsPressedInFrame, TRUE); + heliArrayClear(&buttonsReleasedInFrame, TRUE); + ++frameCount; + } else { + double dt = 1/frameRate; + guint64 timeStep = (guint64)round(dt*1e6); + while(currentTime < newTime) { + currentTime += timeStep; + ++frameCount; + heliUpdateSprites(dt); + if (drawCallback) drawCallback(); + heliArrayClear(&keysPressedInFrame, TRUE); + heliArrayClear(&keysReleasedInFrame, TRUE); + heliArrayClear(&buttonsPressedInFrame, TRUE); + heliArrayClear(&buttonsReleasedInFrame, TRUE); + } + } + + heliCairo = NULL; + return TRUE; +} + +static gboolean handleEvent(GtkWidget *widget G_GNUC_UNUSED, GdkEvent *event, gpointer data G_GNUC_UNUSED) { + gchar *keyname; + int button; + + switch(event->type) { + case GDK_KEY_PRESS: + keyname = heliStringCopy( gdk_keyval_name(event->key.keyval) ); + heliLowercase(keyname); + heliStringsetAdd(&keysPressed, keyname); + heliStringsetAdd(&keysPressedInFrame, keyname); + free(keyname); + return TRUE; + case GDK_KEY_RELEASE: + keyname = heliStringCopy( gdk_keyval_name(event->key.keyval) ); + heliLowercase(keyname); + heliStringsetRemove(&keysPressed, keyname); + heliStringsetAdd(&keysReleasedInFrame, keyname); + free(keyname); + return TRUE; + case GDK_BUTTON_PRESS: + button = event->button.button; + if (button >= 0 && button < buttonsCount) { + heliStringsetAdd(&buttonsPressed, buttonNames[button]); + heliStringsetAdd(&buttonsPressedInFrame, buttonNames[button]); + } + _mouseX = event->button.x; + _mouseY = event->button.y; + return TRUE; + case GDK_BUTTON_RELEASE: + button = event->button.button; + if (button >= 0 && button < buttonsCount) { + heliStringsetRemove(&buttonsPressed, buttonNames[button]); + heliStringsetAdd(&buttonsReleasedInFrame, buttonNames[button]); + } + _mouseX = event->button.x; + _mouseY = event->button.y; + return TRUE; + case GDK_MOTION_NOTIFY: + _mouseX = event->motion.x; + _mouseY = event->motion.y; + return TRUE; + default: + break; + } + return FALSE; +} + +static void activate(GtkApplication* app, gpointer data G_GNUC_UNUSED) { + window = gtk_application_window_new(app); + g_signal_connect(window, "draw", G_CALLBACK(draw), NULL); + g_signal_connect(window, "event", G_CALLBACK(handleEvent), NULL); + gtk_widget_add_events( window, + GDK_POINTER_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_KEY_PRESS_MASK + | GDK_KEY_RELEASE_MASK ); + gtk_widget_set_size_request(window, width, height); + gtk_widget_show(window); + timerInterval = (guint)round(1000/frameRate); + g_timeout_add(timerInterval, timeout, NULL); + if (initCallback) initCallback(); +} + +void worldRun() { + if (started) return; + started = TRUE; + stopped = FALSE; + + frameCount = 0; + srand(time(NULL)); + + GtkApplication *application = gtk_application_new(NULL, 0); + g_signal_connect(application, "activate", G_CALLBACK(activate), NULL); + g_application_run(G_APPLICATION(application), 0, NULL); + g_object_unref(application); + + while(worldGetSpriteCount()) + { spriteDestroy(worldGetSprite(0)); } + + heliArrayDestroy(&keysPressed, TRUE); + heliArrayDestroy(&keysPressed, TRUE); + heliArrayDestroy(&keysPressedInFrame, TRUE); + heliArrayDestroy(&keysReleasedInFrame, TRUE); + heliArrayDestroy(&buttonsPressed, TRUE); + heliArrayDestroy(&buttonsPressedInFrame, TRUE); + heliArrayDestroy(&buttonsReleasedInFrame, TRUE); + + started = FALSE; +} diff --git a/heliantus/world.h b/heliantus/world.h new file mode 100644 index 0000000..1500d83 --- /dev/null +++ b/heliantus/world.h @@ -0,0 +1,70 @@ +#ifndef HELI_WORLD_H +#define HELI_WORLD_H + + +#include "common.h" +#include "sprite.h" + + +typedef void (*Callback)(); + + +void drawSprites(); + +void playSound(char *path, int loop); +void stopSound(char *path); + +int keyDown(char *code); +int keyWentDown(char *code); +int keyWentUp(char *code); + +int mouseDidMove(); +int mouseDown(char *code); +int mouseWentDown(char *code); +int mouseWentUp(char *code); +double mouseX(); +double mouseY(); + +int mouseIsOver(Sprite sprite); +int mousePressedOver(Sprite sprite); + + +int worldGetSpriteCount(); +Sprite worldGetSprite(int i); + +int worldGetWidth(); +void worldSetWidth(int width); + +int worldGetHeight(); +void worldSetHeight(int height); + +double worldGetFrameRate(); +void worldSetFrameRate(double frameRate); + +int worldGetFrameCount(); +double worldGetSeconds(); + +void worldSetInit(Callback init); +void worldSetDraw(Callback draw); +void worldRun(); +void worldStop(); + + +void cameraOn(); +void cameraOff(); +int cameraIsActive(); + +double cameraMouseX(); +double cameraMouseY(); + +double cameraGetX(); +void cameraSetX(double x); + +double cameraGetY(); +void cameraSetY(double y); + +double cameraGetZoom(); +void cameraSetZoom(double zoom); + + +#endif diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..1a77d87 --- /dev/null +++ b/test/main.c @@ -0,0 +1,15 @@ + +#include + +void init() { +} + +void draw() { +} + +int main() { + worldSetInit(&init); + worldSetDraw(&draw); + worldRun(); + return 0; +}