Add Earth sprite to moon parallax background

Render earth.png as a non-tiling feature sprite in the moon sky,
drawn between the far starfield and near crater terrain layers.

Introduce ParallaxFeature struct for single-instance background
sprites that scroll with the camera but never tile. Clean up the
feature reference in parallax_free to prevent stale pointers
between level transitions.
This commit is contained in:
Thomas
2026-03-01 17:49:14 +00:00
parent 6c4b076c68
commit fdba6ef077
3 changed files with 50 additions and 3 deletions

BIN
assets/sprites/earth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,4 +1,5 @@
#include "engine/parallax.h" #include "engine/parallax.h"
#include "engine/assets.h"
#include "engine/camera.h" #include "engine/camera.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
@@ -795,6 +796,21 @@ static void generate_moon_far(Parallax *p, SDL_Renderer *renderer) {
p->far_layer.scroll_y = 0.03f; p->far_layer.scroll_y = 0.03f;
p->far_layer.active = true; p->far_layer.active = true;
p->far_layer.owns_texture = true; p->far_layer.owns_texture = true;
/* Earth in the sky — non-tiling feature sprite */
SDL_Texture *earth_tex = assets_get_texture("assets/sprites/earth.png");
if (earth_tex) {
int ew, eh;
SDL_QueryTexture(earth_tex, NULL, NULL, &ew, &eh);
p->feature.texture = earth_tex;
p->feature.tex_w = ew;
p->feature.tex_h = eh;
p->feature.x = (float)(w / 4);
p->feature.y = (float)(h * 0.08f);
p->feature.scroll_x = 0.03f; /* same as far layer */
p->feature.scroll_y = 0.03f;
p->feature.active = true;
}
} }
static void generate_moon_near(Parallax *p, SDL_Renderer *renderer) { static void generate_moon_near(Parallax *p, SDL_Renderer *renderer) {
@@ -953,9 +969,25 @@ static void render_layer(const ParallaxLayer *layer, const Camera *cam,
} }
} }
static void render_feature(const ParallaxFeature *f, const Camera *cam,
SDL_Renderer *renderer) {
if (!f->active || !f->texture) return;
/* Scroll with camera but do not tile */
int draw_x = (int)(f->x - cam->pos.x * f->scroll_x);
int draw_y = (int)(f->y - cam->pos.y * f->scroll_y);
SDL_Rect dst = {draw_x, draw_y, f->tex_w, f->tex_h};
if (dst.x + dst.w < 0 || dst.x >= SCREEN_WIDTH) return;
if (dst.y + dst.h < 0 || dst.y >= SCREEN_HEIGHT) return;
SDL_RenderCopy(renderer, f->texture, NULL, &dst);
}
void parallax_render(const Parallax *p, const Camera *cam, SDL_Renderer *renderer) { void parallax_render(const Parallax *p, const Camera *cam, SDL_Renderer *renderer) {
if (!p || !cam) return; if (!p || !cam) return;
render_layer(&p->far_layer, cam, renderer); render_layer(&p->far_layer, cam, renderer);
render_feature(&p->feature, cam, renderer);
render_layer(&p->near_layer, cam, renderer); render_layer(&p->near_layer, cam, renderer);
} }
@@ -974,4 +1006,8 @@ void parallax_free(Parallax *p) {
} }
p->near_layer.texture = NULL; p->near_layer.texture = NULL;
p->near_layer.active = false; p->near_layer.active = false;
/* Feature sprite is asset-manager-owned — just clear the reference */
p->feature.texture = NULL;
p->feature.active = false;
} }

View File

@@ -18,10 +18,21 @@ typedef struct ParallaxLayer {
bool owns_texture; /* true if we generated it (must free) */ bool owns_texture; /* true if we generated it (must free) */
} ParallaxLayer; } ParallaxLayer;
/* Parallax background system — up to two layers */ /* A non-tiling sprite drawn once in the background (e.g. Earth from moon) */
typedef struct ParallaxFeature {
SDL_Texture *texture; /* sprite image */
int tex_w, tex_h; /* sprite dimensions */
float x, y; /* base position (pixels, screen) */
float scroll_x; /* horizontal scroll factor */
float scroll_y; /* vertical scroll factor */
bool active;
} ParallaxFeature;
/* Parallax background system — two tiling layers + optional feature sprite */
typedef struct Parallax { typedef struct Parallax {
ParallaxLayer far_layer; /* distant background (stars) */ ParallaxLayer far_layer; /* distant background (stars) */
ParallaxLayer near_layer; /* mid-ground background (nebula) */ ParallaxLayer near_layer; /* mid-ground background (nebula) */
ParallaxFeature feature; /* non-tiling overlay (planet, etc.) */
} Parallax; } Parallax;
/* Initialize parallax (zeroes everything) */ /* Initialize parallax (zeroes everything) */