Skip to content

Commit c009c93

Browse files
committed
Bouncing logo idea
Signed-off-by: Joachim Wiberg <[email protected]>
1 parent ce1c4e8 commit c009c93

File tree

5 files changed

+141
-10
lines changed

5 files changed

+141
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
demo
33
font_data.h
44
image_data.h
5+
logo_data.h
56
music_data.h
67
AppDir/
78
appimagetool

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ DEBUGFLAGS = -g -O0 -DDEBUG
77

88
TARGET = demo
99
SOURCE = demo.c
10-
HEADERS = font_data.h image_data.h
10+
HEADERS = font_data.h image_data.h logo_data.h
1111

1212
# Check if music file exists and add to build
1313
ifneq ($(wildcard music.mod),)
@@ -25,6 +25,10 @@ font_data.h: topaz-8.otf
2525
image_data.h: jack.png
2626
xxd -i jack.png > image_data.h
2727

28+
# Generate embedded logo data from logo.png
29+
logo_data.h: logo.png
30+
xxd -i logo.png > logo_data.h
31+
2832
# Generate embedded music data from music.mod (if present)
2933
music_data.h: music.mod
3034
xxd -i music.mod > music_data.h
@@ -39,7 +43,7 @@ run: $(TARGET)
3943
./$(TARGET)
4044

4145
clean:
42-
rm -f $(TARGET) font_data.h image_data.h music_data.h
46+
rm -f $(TARGET) font_data.h image_data.h logo_data.h music_data.h
4347
rm -rf AppDir appimagetool InfixDemo-x86_64.AppImage
4448

4549
docker-build:

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ oldschool aesthetics.
77

88
The demo cycles through different scenes.
99

10-
**Starfield** — 3D scrolling stars with sine wave text scroller
11-
**Plasma** — Colorful plasma effect with sine wave text scroller
12-
**Rotating Cube** — Texture-mapped 3D cube with copper bars background and traditional bottom scroller
10+
**Starfield** — 3D scrolling stars with sine wave text scroller
11+
**Plasma** — Colorful plasma effect with sine wave text scroller
12+
**Rotating Cube** — Texture-mapped 3D cube with copper bars background and traditional bottom scroller
1313
**Tunnel** — Psychedelic tunnel effect with traditional bottom scroller
14+
**Bouncing Logo** — Animated logo with bouncing physics and rotation effects
1415

1516
## Dependencies
1617

@@ -46,6 +47,7 @@ Or run a specific scene:
4647

4748
```
4849
./demo 2 # Run only the cube scene
50+
./demo 4 # Run only the bouncing logo scene
4951
```
5052

5153
## Distribution

demo.c

Lines changed: 129 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
/* Embedded font, image, and music data */
1717
#include "font_data.h"
1818
#include "image_data.h"
19+
#include "logo_data.h"
1920

2021
/* Music data will be included when available */
2122
#ifdef HAVE_MUSIC
@@ -46,6 +47,8 @@ typedef struct {
4647
TTF_Font *font;
4748
SDL_Surface *jack_surface;
4849
SDL_Texture *jack_texture;
50+
SDL_Surface *logo_surface;
51+
SDL_Texture *logo_texture;
4952
int current_scene;
5053
int fixed_scene;
5154
float time;
@@ -415,6 +418,95 @@ void render_tunnel(DemoContext *ctx) {
415418
}
416419
}
417420

421+
/* Bouncing logo effect with squash and stretch */
422+
void render_bouncing_logo(DemoContext *ctx) {
423+
static float squash_x = 1.0f; /* Horizontal scale factor */
424+
static float squash_y = 1.0f; /* Vertical scale factor */
425+
static float prev_x = -1.0f; /* Previous x position */
426+
static float prev_y = -1.0f; /* Previous y position */
427+
428+
/* Clear to dark blue background */
429+
for (int i = 0; i < WIDTH * HEIGHT; i++) {
430+
ctx->pixels[i] = 0xFF001020;
431+
}
432+
433+
if (!ctx->logo_texture) {
434+
SDL_UpdateTexture(ctx->texture, NULL, ctx->pixels, WIDTH * sizeof(Uint32));
435+
SDL_RenderClear(ctx->renderer);
436+
SDL_RenderCopy(ctx->renderer, ctx->texture, NULL, NULL);
437+
return;
438+
}
439+
440+
/* Get logo dimensions */
441+
int logo_w, logo_h;
442+
SDL_QueryTexture(ctx->logo_texture, NULL, NULL, &logo_w, &logo_h);
443+
444+
/* Bouncing physics with sine waves for smooth motion */
445+
float t = ctx->time;
446+
float bounce_x = sin(t * 0.8) * (WIDTH - logo_w) / 2 + (WIDTH - logo_w) / 2;
447+
float bounce_y = fabs(sin(t * 1.1)) * (HEIGHT - logo_h - 50) + 25;
448+
449+
/* Detect edge collisions by checking velocity direction changes */
450+
float squash_intensity = 0.1f; /* How much to squash (0.1 = 10% compression) */
451+
float recovery_speed = 0.25f; /* How fast to recover to normal */
452+
453+
/* Check horizontal collision (left/right edges) */
454+
/*if (prev_x >= 0) {
455+
float dx = bounce_x - prev_x;
456+
// Detect direction change = wall hit
457+
if ((prev_x <= 5 && dx > 0) || (prev_x >= WIDTH - logo_w - 5 && dx < 0)) {
458+
squash_x = 1.0f - squash_intensity; // Squash horizontally
459+
squash_y = 1.0f + squash_intensity; // Stretch vertically
460+
}
461+
}*/
462+
463+
/* Check vertical collision (top/bottom edges) */
464+
if (prev_y >= 0) {
465+
float dy = bounce_y - prev_y;
466+
/* Detect direction change = floor/ceiling hit */
467+
if ((prev_y <= 30 && dy > 0) || (prev_y >= HEIGHT - logo_h - 30 && dy < 0)) {
468+
squash_y = 1.0f - squash_intensity; /* Squash vertically */
469+
squash_x = 1.0f + squash_intensity; /* Stretch horizontally */
470+
}
471+
}
472+
473+
/* Smoothly recover to normal scale */
474+
squash_x += (1.0f - squash_x) * recovery_speed;
475+
squash_y += (1.0f - squash_y) * recovery_speed;
476+
477+
/* Clamp to prevent overshoot */
478+
if (fabs(squash_x - 1.0f) < 0.01f) squash_x = 1.0f;
479+
if (fabs(squash_y - 1.0f) < 0.01f) squash_y = 1.0f;
480+
481+
/* Store position for next frame */
482+
prev_x = bounce_x;
483+
prev_y = bounce_y;
484+
485+
/* Add some gentle rotation */
486+
float rotation = sin(t * 0.5) * 8.0; /* ±8 degrees */
487+
488+
/* Apply squash and stretch to dimensions */
489+
int scaled_w = (int)(logo_w * squash_x);
490+
int scaled_h = (int)(logo_h * squash_y);
491+
492+
/* Center the scaled logo at the bounce position */
493+
SDL_Rect dest_rect = {
494+
(int)(bounce_x + (logo_w - scaled_w) / 2),
495+
(int)(bounce_y + (logo_h - scaled_h) / 2),
496+
scaled_w,
497+
scaled_h
498+
};
499+
500+
/* Update background texture */
501+
SDL_UpdateTexture(ctx->texture, NULL, ctx->pixels, WIDTH * sizeof(Uint32));
502+
SDL_RenderClear(ctx->renderer);
503+
SDL_RenderCopy(ctx->renderer, ctx->texture, NULL, NULL);
504+
505+
/* Render the rotating, squashing logo */
506+
SDL_RenderCopyEx(ctx->renderer, ctx->logo_texture, NULL, &dest_rect,
507+
rotation, NULL, SDL_FLIP_NONE);
508+
}
509+
418510
/* Scroll text rendering with different styles */
419511
void render_scroll_text(DemoContext *ctx) {
420512
const char *text = " INFIX - CONTAINER DEMO"
@@ -594,22 +686,23 @@ int main(int argc, char *argv[]) {
594686
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
595687
printf("Usage: %s [scene]\n", argv[0]);
596688
printf("Scenes:\n");
597-
printf(" 0 - Plasma\n");
598-
printf(" 1 - Scroller\n");
689+
printf(" 0 - Starfield\n");
690+
printf(" 1 - Plasma\n");
599691
printf(" 2 - Cube\n");
600692
printf(" 3 - Tunnel\n");
693+
printf(" 4 - Bouncing Logo\n");
601694
printf("\nIf no scene is specified, auto-switches between all scenes.\n");
602695
IMG_Quit();
603696
TTF_Quit();
604697
SDL_Quit();
605698
return 0;
606699
}
607700
int scene = atoi(argv[1]);
608-
if (scene >= 0 && scene <= 3) {
701+
if (scene >= 0 && scene <= 4) {
609702
ctx.fixed_scene = scene;
610703
ctx.current_scene = scene;
611704
} else {
612-
fprintf(stderr, "Invalid scene number. Use 0-3.\n");
705+
fprintf(stderr, "Invalid scene number. Use 0-4.\n");
613706
IMG_Quit();
614707
TTF_Quit();
615708
SDL_Quit();
@@ -696,6 +789,26 @@ int main(int argc, char *argv[]) {
696789
}
697790
}
698791

792+
/* Load embedded logo.png from memory */
793+
SDL_RWops *logo_rw = SDL_RWFromConstMem(logo_png, logo_png_len);
794+
if (!logo_rw) {
795+
fprintf(stderr, "Warning: Failed to create RWops for logo: %s\n", SDL_GetError());
796+
fprintf(stderr, "Bouncing logo scene will not render.\n");
797+
ctx.logo_texture = NULL;
798+
ctx.logo_surface = NULL;
799+
} else {
800+
ctx.logo_surface = IMG_Load_RW(logo_rw, 1); /* 1 = automatically close RW */
801+
if (!ctx.logo_surface) {
802+
fprintf(stderr, "Warning: Failed to load embedded logo: %s\n", IMG_GetError());
803+
fprintf(stderr, "Bouncing logo scene will not render.\n");
804+
ctx.logo_texture = NULL;
805+
} else {
806+
/* Create and cache the texture */
807+
ctx.logo_texture = SDL_CreateTextureFromSurface(ctx.renderer, ctx.logo_surface);
808+
SDL_SetTextureBlendMode(ctx.logo_texture, SDL_BLENDMODE_BLEND);
809+
}
810+
}
811+
699812
/* Initialize starfield */
700813
for (int i = 0; i < NUM_STARS; i++) {
701814
ctx.stars[i].x = (rand() % 2000 - 1000) / 10.0f;
@@ -757,7 +870,7 @@ int main(int argc, char *argv[]) {
757870
} else if (fade_progress < 2.0f) {
758871
/* Switch scene and fade in */
759872
if (ctx.fade_alpha < 0.5f) {
760-
ctx.current_scene = (ctx.current_scene + 1) % 4;
873+
ctx.current_scene = (ctx.current_scene + 1) % 5;
761874
scene_start = current_time - (Uint32)fade_duration;
762875
ctx.time = 0;
763876
}
@@ -804,6 +917,11 @@ int main(int argc, char *argv[]) {
804917
SDL_RenderCopy(ctx.renderer, ctx.texture, NULL, NULL);
805918
render_scroll_text(&ctx);
806919
break;
920+
case 4:
921+
ctx.scroll_style = SCROLL_BOTTOM_TRADITIONAL;
922+
render_bouncing_logo(&ctx);
923+
render_scroll_text(&ctx);
924+
break;
807925
}
808926

809927
/* Apply fade effect */
@@ -825,6 +943,12 @@ int main(int argc, char *argv[]) {
825943
if (ctx.jack_texture) {
826944
SDL_DestroyTexture(ctx.jack_texture);
827945
}
946+
if (ctx.logo_surface) {
947+
SDL_FreeSurface(ctx.logo_surface);
948+
}
949+
if (ctx.logo_texture) {
950+
SDL_DestroyTexture(ctx.logo_texture);
951+
}
828952
if (ctx.plasma_texture) {
829953
SDL_DestroyTexture(ctx.plasma_texture);
830954
}

logo.png

23.4 KB
Loading

0 commit comments

Comments
 (0)