From 59dae55437c1ea326792a5897d5bcc03cad938ba Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Jul 22 2020 12:18:53 +0000 Subject: opengl sprites demo --- diff --git a/demo/data-src/bricks-tile.xcf b/demo/data-src/bricks-tile.xcf new file mode 100644 index 0000000..5ef1208 Binary files /dev/null and b/demo/data-src/bricks-tile.xcf differ diff --git a/demo/data-src/snake.xcf b/demo/data-src/snake.xcf new file mode 100644 index 0000000..ceafa0c Binary files /dev/null and b/demo/data-src/snake.xcf differ diff --git a/demo/data/sprite/bricks-tile.png b/demo/data/sprite/bricks-tile.png new file mode 100644 index 0000000..edf0b7e Binary files /dev/null and b/demo/data/sprite/bricks-tile.png differ diff --git a/demo/data/sprite/snail-indexed.png b/demo/data/sprite/snail-indexed.png new file mode 100644 index 0000000..803f7f1 Binary files /dev/null and b/demo/data/sprite/snail-indexed.png differ diff --git a/demo/data/sprite/snake.png b/demo/data/sprite/snake.png new file mode 100644 index 0000000..6f7d9bf Binary files /dev/null and b/demo/data/sprite/snake.png differ diff --git a/demo/src/SConstruct b/demo/src/SConstruct index 19b17e6..b813931 100644 --- a/demo/src/SConstruct +++ b/demo/src/SConstruct @@ -13,7 +13,10 @@ flags = ' -O0 -g -lm -Wall -fmessage-length=0 ' # files -sources = [ 'main.c' ] +sources = [ + 'main.c', + 'phisics.c', + 'sprites.c' ] # build diff --git a/demo/src/main.c b/demo/src/main.c index 961941e..dd5ce42 100644 --- a/demo/src/main.c +++ b/demo/src/main.c @@ -1,73 +1,25 @@ #include -Sprite ball, brick1, brick2, brick3; -Group edges; -Group movement; -Sound beep; +#include "phisics.h" +#include "sprites.h" -void init() { - ball = createSpriteEx(200, 200, 64, 64); - spriteSetAnimation(ball, "data/sprite/breadball.png"); - spriteSetColliderCircle(ball, 0, 0, -1); - spriteSetRotateToDirection(ball, TRUE); - - brick1 = createSpriteEx(200-32, 200+64, 64, 64); - spriteSetAnimation(brick1, "data/sprite/bricks.png"); - spriteSetTintColor(brick1, rgb(0, 0, 1)); - spriteSetColliderRectangle(brick1, 0, 0, 0, -1, -1, 20); - spriteSetBounciness(brick1, 0.5); - - brick2 = createSpriteEx(200+32, 200+64, 64, 64); - spriteSetAnimation(brick2, "data/sprite/bricks.png"); - spriteSetColliderRectangle(brick2, 0, 0, 0, -1, -1, 20); - - brick3 = createSpriteEx(200+32+64, 200+64, 64, 64); - spriteSetAnimation(brick3, "data/sprite/bricks.png"); - spriteSetTintColor(brick3, rgba(1, 0, 1, 0.5)); - spriteSetColliderRectangle(brick3, 0, 0, 0, -1, -1, 20); - spriteSetBounciness(brick3, 2); - - movement = createGroup(); - groupAdd(movement, ball); - groupAdd(movement, brick2); - - edges = createEdgesGroup(); - groupAdd(edges, brick1); - groupAdd(edges, brick3); - beep = createSound("data/sound/beep.ogg"); +void init() { + phisicsInit(); + spritesInit(); } void draw() { - double dt = worldGetTimeStep(); - double accel = 100; - - double vx = spriteGetVelocityX(ball); - double vy = spriteGetVelocityY(ball); - if (keyDown("left")) spriteSetVelocityX(ball, vx - accel*dt); - if (keyDown("right")) spriteSetVelocityX(ball, vx + accel*dt); - if (keyDown("up")) spriteSetVelocityY(ball, vy - accel*dt); - if (keyDown("down")) spriteSetVelocityY(ball, vy + accel*dt); - - if (mouseWentDown("left")) soundPlay(beep, FALSE); - if (mouseWentDown("middle")) { - char text[1000]; - askTextEx("Test?", text, sizeof(text), TRUE, FALSE); - } - - int collision = FALSE; - if (groupCollideBetween(movement, 1)) collision = TRUE; - if (groupPushGroup(edges, movement, 0.9)) collision = TRUE; + phisicsDraw(); + spritesDraw(); - if (collision) soundPlay(beep, FALSE); - drawSprites(); - point(mouseX(), mouseY()); } int main() { + worldSetWidth(1024); worldSetInit(&init); worldSetDraw(&draw); worldRun(); diff --git a/demo/src/phisics.c b/demo/src/phisics.c new file mode 100644 index 0000000..e34cd6d --- /dev/null +++ b/demo/src/phisics.c @@ -0,0 +1,74 @@ + +#include + +#include "phisics.h" + + + +static Sprite ball, brick1, brick2, brick3; +static Group edges; +static Group movement; + +Sound beep; + + + +void phisicsInit() { + ball = createSpriteEx(200, 200, 64, 64); + spriteSetAnimation(ball, "data/sprite/breadball.png"); + spriteSetColliderCircle(ball, 0, 0, -1); + spriteSetRotateToDirection(ball, TRUE); + + brick1 = createSpriteEx(200-32, 200+64, 64, 64); + spriteSetAnimation(brick1, "data/sprite/bricks.png"); + spriteSetTintColor(brick1, rgb(0, 0, 1)); + spriteSetColliderRectangle(brick1, 0, 0, 0, -1, -1, 20); + spriteSetBounciness(brick1, 0.5); + + brick2 = createSpriteEx(200+32, 200+64, 64, 64); + spriteSetAnimation(brick2, "data/sprite/bricks.png"); + spriteSetColliderRectangle(brick2, 0, 0, 0, -1, -1, 20); + + brick3 = createSpriteEx(200+32+64, 200+64, 64, 64); + spriteSetAnimation(brick3, "data/sprite/bricks.png"); + spriteSetTintColor(brick3, rgba(1, 0, 1, 0.5)); + spriteSetColliderRectangle(brick3, 0, 0, 0, -1, -1, 20); + spriteSetBounciness(brick3, 2); + + movement = createGroup(); + groupAdd(movement, ball); + groupAdd(movement, brick2); + + edges = createEdgesGroup(); + groupAdd(edges, brick1); + groupAdd(edges, brick3); + + + beep = createSound("data/sound/beep.ogg"); +} + + +void phisicsDraw() { + double dt = worldGetTimeStep(); + double accel = 100; + + double vx = spriteGetVelocityX(ball); + double vy = spriteGetVelocityY(ball); + if (keyDown("left")) spriteSetVelocityX(ball, vx - accel*dt); + if (keyDown("right")) spriteSetVelocityX(ball, vx + accel*dt); + if (keyDown("up")) spriteSetVelocityY(ball, vy - accel*dt); + if (keyDown("down")) spriteSetVelocityY(ball, vy + accel*dt); + + if (mouseWentDown("left")) soundPlay(beep, FALSE); + if (mouseWentDown("middle")) { + char text[1000]; + askTextEx("Test?", text, sizeof(text), TRUE, FALSE); + } + + int collision = FALSE; + if (groupCollideBetween(movement, 1)) collision = TRUE; + if (groupPushGroup(edges, movement, 0.9)) collision = TRUE; + + if (collision) soundPlay(beep, FALSE); +} + diff --git a/demo/src/phisics.h b/demo/src/phisics.h new file mode 100644 index 0000000..f3dbdbb --- /dev/null +++ b/demo/src/phisics.h @@ -0,0 +1,9 @@ +#ifndef PHISICS_H +#define PHISICS_H + + +void phisicsInit(); +void phisicsDraw(); + + +#endif diff --git a/demo/src/sprites.c b/demo/src/sprites.c new file mode 100644 index 0000000..1657ac7 --- /dev/null +++ b/demo/src/sprites.c @@ -0,0 +1,112 @@ + +#include + +#include + +#include "sprites.h" + + +Group pulse; + + +void spritesInit() { + pulse = createGroup(); + + Sprite s; + double x = 1024 - 6*64 + 48/2; + double y = 16 + 48/2; + + // normal + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks.png"); + groupAdd(pulse, s); + x += 64; + + // indexed colors + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/snail-indexed.png"); + groupAdd(pulse, s); + x += 64; + + // without alpha + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + groupAdd(pulse, s); + x += 64; + + // without texture + s = createSpriteEx(x, y, 48, 48); + spriteSetShapeColor(s, "blue"); + groupAdd(pulse, s); + x += 64; + + // with tint color + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks.png"); + spriteSetTintColor(s, "red"); + groupAdd(pulse, s); + x += 64; + + // semi-transparent + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks.png"); + spriteSetTintColor(s, rgba(1, 1, 1, 0.5)); + groupAdd(pulse, s); + x += 64; + + x = 1024 - 16 - 48/2; + y += 64; + + // tiles + s = createSpriteEx(x - 48/2, y + 48/2, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks.png"); + groupAdd(pulse, s); + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + s = createSpriteEx(x, y + 48, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + x -= 48; + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + s = createSpriteEx(x, y + 48, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + x -= 64; + + // blend two sprites + s = createSpriteEx(x, y, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + spriteSetTintColor(s, rgba(1, 1, 1, 0.5)); + groupAdd(pulse, s); + x -= 16; + s = createSpriteEx(x, y + 16, 48, 48); + spriteSetAnimation(s, "data/sprite/bricks-tile.png"); + spriteSetTintColor(s, rgba(1, 1, 1, 0.5)); + groupAdd(pulse, s); + x -= 64; + + // texture size is not power of two + double k = 0.25, w = 343*k, h = 221*k; + x += 48/2 - w/2; + s = createSpriteEx(x, y, w, h); + spriteSetAnimation(s, "data/sprite/snake.png"); + groupAdd(pulse, s); +} + + +void spritesDraw() { + const double shift = PI/4; + const double scalePeriod = 1; + const double scaleAmplitude = 0.1; + const double rotatePeriod = 2; + const double rotateAmplitude = 30; + + double time = worldGetSeconds(); + for(int i = 0; i < groupGetCount(pulse); ++i) { + double scale = exp( scaleAmplitude * sin(shift + time/scalePeriod*2*PI) ); + double rotation = rotateAmplitude * sin(shift + time/rotatePeriod*2*PI); + + Sprite s = groupGet(pulse, i); + spriteSetScale(s, scale); + spriteSetRotation(s, rotation); + } +} diff --git a/demo/src/sprites.h b/demo/src/sprites.h new file mode 100644 index 0000000..5d16610 --- /dev/null +++ b/demo/src/sprites.h @@ -0,0 +1,9 @@ +#ifndef SPRITES_H +#define SPRITES_H + + +void spritesInit(); +void spritesDraw(); + + +#endif diff --git a/src/animation.c b/src/animation.c index d7e7a42..54f90fb 100644 --- a/src/animation.c +++ b/src/animation.c @@ -96,8 +96,8 @@ static unsigned int loadFrame(const char *path) { int fh = fixsize(h); if (fw != w || fh != h) { float *fbuffer = (float*)malloc((size_t)fw*fh*4*sizeof(float)); - double kr = (double)w/fw; - double kc = (double)h/fh; + double kr = (double)h/fh; + double kc = (double)w/fw; for(int r = 0; r < fh; ++r) { for(int c = 0; c < fw; ++c) { double pr1 = r*kr; @@ -112,7 +112,7 @@ static unsigned int loadFrame(const char *path) { int c0 = (int)floor(pc1 + HELI_PRECISION); pc1 -= c0; int c1 = c0 + 1; - if (c1 >= h) c1 = h - 1; + if (c1 >= w) c1 = w - 1; if (c0 > c1) c0 = c1; double pc0 = 1 - pc1; @@ -149,6 +149,7 @@ static unsigned int loadFrame(const char *path) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.7f); // build mip levels unsigned char *ibuffer = malloc((size_t)w*h*4); diff --git a/src/common.c b/src/common.c index e58e2eb..24d3959 100644 --- a/src/common.c +++ b/src/common.c @@ -11,26 +11,26 @@ struct _Directory { }; -static char *colors[] = { - "transparent", "0 0 0 0", +static char *colors[][2] = { + { "transparent", "0 0 0 0" }, - "black", "0 0 0 1", - "white", "1 1 1 1", - "gray", "0.5 0.5 0.5 1", + { "black", "0 0 0 1" }, + { "white", "1 1 1 1" }, + { "gray", "0.5 0.5 0.5 1" }, - "red", "1 0 0 1", - "green" "0 1 0 1", - "blue" "0 0 1 1", + { "red", "1 0 0 1" }, + { "green", "0 1 0 1" }, + { "blue", "0 0 1 1" }, - "yellow", "1 1 0 1", - "magenta", "1 0 1 1", - "cyan", "0 1 1 1", - - "yellow", "1 1 0 1", - "magenta", "1 0 1 1", - "cyan", "0 1 1 1", + { "yellow", "1 1 0 1" }, + { "magenta", "1 0 1 1" }, + { "cyan", "0 1 1 1" }, + + { "yellow", "1 1 0 1" }, + { "magenta", "1 0 1 1" }, + { "cyan", "0 1 1 1" }, - "brown", "0.5 0.5 0 1", + { "brown", "0.5 0.5 0 1" }, }; @@ -123,7 +123,7 @@ void heliParseColor(const char *x, double *color) { if (*x == '#') { ++x; int hex[8] = { 0, 0, 0, 0, 0, 0, 15, 15 }; - for(int i = 0; *x && i < 8; ++i) { + for(int i = 0; *x && i < 8; ++i, ++x) { char c = tolower(*x); if (c >= '0' && c <= '9') hex[i] = c - '0'; if (c >= 'a' && c <= 'f') hex[i] = c - 'a' + 10; @@ -132,10 +132,15 @@ void heliParseColor(const char *x, double *color) { color[i] = (hex[i*2]*16 + hex[i*2 + 1])/255.0; } else if (isalpha(*x)) { - int count = (int)(sizeof(colors)/sizeof(*colors)/2); - for(int i = 0; i < count; ++i) - if (strcmp(x, colors[i*2]) == 0) - { heliParseColor(colors[i*2 + 1], color); return; } + int count = (int)(sizeof(colors)/sizeof(*colors)); + for(int i = 0; i < count; ++i) { + const char *a = x, *b = colors[i][0]; + do { + if (tolower(*a) != tolower(*b)) break; + ++a, ++b; + if (!*a && !*b) { heliParseColor(colors[i][1], color); return; } + } while (*a && *b); + } } else { sscanf(x, "%lf %lf %lf %lf", &color[0], &color[1], &color[2], &color[3]); } diff --git a/src/sprite.c b/src/sprite.c index 9a5238a..1a5b301 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -399,7 +399,7 @@ static void drawSpriteDebug(Sprite s) { } static void drawSprite(Sprite s) { - const double aaBorder = 10; + const double aaBorder = 1; unsigned int texid = s->animation ? (unsigned int)(size_t)heliArrayGetValue(&s->animation->frames, s->frame) : 0u; diff --git a/src/world.c b/src/world.c index 8b33c86..c9a5743 100644 --- a/src/world.c +++ b/src/world.c @@ -96,7 +96,7 @@ int mousePressedOver(Sprite sprite) static void resize(int w, int h) { w = w > 200 ? w : 100; h = h > 200 ? h : 200; - if (width != w && height != h) { + if (width != w || height != h) { width = w; height = h; if (started && !stopped && window)