diff --git a/assets/levels/R2/parallax.toml b/assets/levels/R2/parallax.toml index 1da11cd..0488a3f 100644 --- a/assets/levels/R2/parallax.toml +++ b/assets/levels/R2/parallax.toml @@ -3,7 +3,8 @@ width = 256 height = 32 u0 = 0 v0 = 360 # 104 @ BG1 -scrollx = 0.14 +scrollx = 0 +speedx = 0.14 y0 = 0 single = false @@ -12,7 +13,8 @@ width = 256 height = 16 u0 = 0 v0 = 392 -scrollx = 0.16 +scrollx = 0 +speedx = 0.16 y0 = 32 single = false @@ -21,7 +23,8 @@ width = 256 height = 16 u0 = 0 v0 = 408 -scrollx = 0.18 +scrollx = 0 +speedx = 0.18 y0 = 48 single = false diff --git a/include/parallax.h b/include/parallax.h index f5d7771..76b4eae 100644 --- a/include/parallax.h +++ b/include/parallax.h @@ -40,11 +40,15 @@ typedef struct { uint8_t num_parts; uint8_t is_single; int32_t scrollx; + int32_t speedx; int16_t y0; ParallaxPart *parts; // Calculated on load uint16_t width; + + // State + int32_t rposx; } ParallaxStrip; // Holds all parallax strips for a level diff --git a/src/parallax.c b/src/parallax.c index 24daa10..833419d 100644 --- a/src/parallax.c +++ b/src/parallax.c @@ -38,7 +38,9 @@ load_parallax(Parallax *parallax, const char *filename) strip->num_parts = get_byte(bytes, &b); strip->is_single = get_byte(bytes, &b); strip->scrollx = get_long_be(bytes, &b); + strip->speedx = get_long_be(bytes, &b); strip->y0 = get_short_be(bytes, &b); + strip->rposx = 0; strip->parts = alloc_arena_malloc( &_level_arena, @@ -75,11 +77,17 @@ parallax_draw(Parallax *prl, Camera *camera, // Cast multiplication to avoid sign extension on bit shift // This gets the mult. result but also removes the decimal part int32_t stripx = (uint32_t)(camera_vx * strip->scrollx) >> 24; + + // Update strip relative position when there's speed involved + strip->rposx -= strip->speedx; + if((strip->rposx >> 12) < -((int32_t)strip->width)) + strip->rposx = 0; + for(uint8_t pi = 0; pi < strip->num_parts; pi++) { ParallaxPart *part = &strip->parts[pi]; // Calculate part X position based on factor and camera (int format) - int32_t vx = ((int32_t)part->offsetx) - stripx; + int32_t vx = ((int32_t)part->offsetx) - stripx + (strip->rposx >> 12); // Given that each part is a horizontal piece of a strip, we assume // that these parts repeat at every (strip width), so just draw diff --git a/tools/buildprl/buildprl.py b/tools/buildprl/buildprl.py index 107793c..9bc851b 100755 --- a/tools/buildprl/buildprl.py +++ b/tools/buildprl/buildprl.py @@ -40,6 +40,7 @@ class ParallaxPart: class ParallaxStrip: single: bool = False scrollx: float = 0 + speedx: float = 0 y0: int = 0 parts: [ParallaxPart] = field(default_factory=list) @@ -47,6 +48,7 @@ class ParallaxStrip: f.write(c_ubyte(len(self.parts))) f.write(c_ubyte(int(self.single))) f.write(c_int(tofixed12(self.scrollx))) + f.write(c_int(tofixed12(self.speedx))) f.write(c_short(self.y0)) for p in self.parts: p.write_to(f) @@ -69,6 +71,7 @@ def parse(data) -> Parallax: strip = ParallaxStrip() strip.single = strip_data.get("single", False) strip.scrollx = strip_data.get("scrollx", 0) + strip.speedx = strip_data.get("speedx", 0) strip.y0 = strip_data.get("y0") height = strip_data.get("height") # Reserved parts = strip_data.get("parts") diff --git a/tools/layouts/prl.hexpat b/tools/layouts/prl.hexpat index 08d3016..54e4291 100644 --- a/tools/layouts/prl.hexpat +++ b/tools/layouts/prl.hexpat @@ -12,6 +12,7 @@ struct ParallaxStrip { u8 num_parts; u8 is_single; be s32 scrollx; + be s32 speedx; be s16 y0; ParallaxPart parts[num_parts]; };