Programming Challenge: Confetti Animation

I just finished implementing a confetti animation. It renders a thousand little images on the screen that are moving and spinning around in random looking directions (see attached image/video).

ConfettiSmall

The challenge is, what’s the minimal amount of state you need to keep from the previous frame(s) to render the next frame?

Note: there is no acceleration, each confetti’s movement direction spin rate, though different from each other, are constant.

const std = @import("std");

fn renderConfettiPiece(
    x: u32,
    y: u32,
    angle_degrees: u9,
) void {
    // assume this function is implemented for you
    std.log.info("confetti {},{} {}", .{ x, y, angle_degrees });
}

fn renderConfettiFrame(frame: usize) void {
    // CHALLENGE: insert code to render 1000 confettis
    // for the given frame
    _ = frame;
}

pub fn main() void {
    // animate 10 frames
    for (0..10) |frame| {
        renderConfettiFrame(frame);
    }
}
5 Likes

How about none at all? Pseudo random number generators are deterministic. My strategy: Pick a seed, generate from there.

fn renderConfettiFrame(frame: usize) void {
    const width = 933;
    const height = 644;
    const maxTranslationSpeed = 100;
    const maxRotationSpeed = 10;
    const seed: u64 = 0;

    var randomEngine = std.Random.DefaultPrng.init(seed);
    const random = randomEngine.random();

    const iframe: i32 = @truncate(@as(isize, @bitCast(frame)));
    for (0..1000) |_| {
        const x = random.intRangeAtMostBiased(i32, 0, width);
        const y = random.intRangeAtMostBiased(i32, 0, height);
        const angle = random.intRangeAtMostBiased(i32, 0, 359);
        
        const dx = random.intRangeAtMostBiased(i32, -maxTranslationSpeed, maxTranslationSpeed);
        const dy = random.intRangeAtMostBiased(i32, -maxTranslationSpeed, maxTranslationSpeed);
        const dAngle = random.intRangeAtMostBiased(i32, -maxRotationSpeed, maxRotationSpeed);
        
        renderConfettiPiece(
            @as(u32, @bitCast(x +% (dx *% iframe))),
            @as(u32, @bitCast(y +% (dy *% iframe))),
            @intCast(@mod(angle +% (dAngle *% iframe), 360)),
        );
    }
}
4 Likes