Const in struct: driving me nuts

I thought I was getting it, too. So much for that.

OK, I have a Sprite structure, its init takes a SpritePt, which represents a fixed f32 or a Tween, that’s all good and dandy.

I have a struct representing the ‘Title screen’, it has init(), step() and draw() for Raylib to make it move. My issue is const regarding the Sprite, defined as a file container i.e. not a ‘struct’ but then imported as and where need with @import.

Now, the ‘level’ CONTAINS the Sprite, and a few more fields:

game_state: *g.Gamestate,
font: r.Font,
mp3: r.Music,
sprites: Spritesheet,
star_map: Starmap,
sprite1: Sprite,

The init() creates the sprite, given the base Sprite sheet, which just wraps the Raylib texture for now, nothing complex for now.

So, I have a struct that has a Sprite in it, that I created in the init():

pub fn init(game_state: *g.Gamestate, font: r.Font, mp3: r.Music, star_map: Starmap, sprite_sheet: Spritesheet) !Level_00_Title {
    const sp1 = try Sprite.init(
        Spritesheet.Type.redShip1,
        150.0,
        250.0,
        sprite_sheet,
    );
    return Level_00_Title{
        .game_state = game_state,
        .font = font,
        .mp3 = mp3,
        .sprites = sprite_sheet,
        .star_map = star_map,
        .sprite1 = sp1,
    };
}

And when I come to step update the sprite I get this error:

src/level_00_title.zig:79:17: error: expected type '*sprite', found '*const sprite'
    self.sprite1.step(dT);

Where the hell did *const come from, that is not how I declared it?!

79: self.sprite1.step(dT);

The step method has *Sprite to get the free level of dereference too:

pub fn step(self: *Sprite, dT: f32) void {
}

For reference the level step() is:

pub fn step(self: *Level_00_Title, dT: f32) void {
    r.ClearBackground(r.BLACK);
    r.UpdateMusicStream(self.mp3);
    self.star_map.draw();
    self.star_map.step(dT);
    self.sprite1.step(dT);
    self.sprite1.draw();

    if (r.IsKeyReleased(r.KEY_SPACE)) {
        r.StopMusicStream(self.mp3);
        self.game_state.* = .level_1;
    }
}

Argh. It’s driving me nuts. I have music playing, text, a three coloured vertical scrolling star-field and yet this f* Sprite is getting up my conk I can tell you. It’s obv. I have not yet understood ‘const’ ness WRT to Zig so, I have read and watched a lot but yeah, here we are.

I don’t know the answer from the code snippets you provided, but at least this error message looks strange:

error: expected type '*sprite', found '*const sprite'

I would expect that the type is named Sprite, not sprite.

…also, does it compile if you remove the self.sprite1.step(dT0); call, and if yes what’s the signature of the self.sprite1.draw() function - e.g. is that any different than the .step() function signature?

1 Like

Making the type readable instead of inferring the type can help find the problem too.

const sp1: *const Sprite = try Sprite.init(...)

I always do this. Inferring is for lazy people I think :slight_smile:

Look at the full stacktrace. And also make use of @compileLog().
But hard to say without seeing the full error message.

Likely that you aren’t using a ptr somewhere/passing it as value or defining some instance as a const instead of a var.

So I am lazy?

Writing the full type is great if you understand exactly what it should be, I don’t have that knowledge down pat yet.

Yes, I find that confusing too as the type IS Sprite …when I solve this one I look forward to the brief feeling of satisfaction!

i was just joking. hence the smiley

Looks like you typo’ed sprite somewhere, but that’s not the issue.

Without looking at the actual code that’s causing the problem, I’m gonna go out on a limb here and assume you have this somewhere:

fn doSomething(self: Level_00_Title) void{
  self.sprite1.step(dT);
}

Parameters in Zig are const. Therefore, self is const, and the sprite in it is also const. When a method is called on a value, Zig automatically coerces it to a pointer, if necessary to match the signature. Here, since the sprite is const, it got coerced into a const pointer, hence the error.

4 Likes

Sorry eric, my bad. Somedays I just totally misjudge things. My limited exposure to ziggit so far has been nothing but pleasant.

4 Likes

Ok, after something of a break, I fixed it… it was the variable capture !!!

pub fn step(self: *Sprite, dT: f32) void {
    if (self.tween_x) |*tx| {    // I had |tx| here !
        tx.step(dT);
        self.pos.x = tx.val;
    }
    if (self.tween_y) |*ty| {    // I had |ty| here !
        ty.step(dT);
        self.pos.y = ty.val;
    }
}

Along the way I got some great advice, found some good stuff to read and learned a lot more about zig; my space ship now tweens perfectly, thanks all.

Now I am working on a TweenStream: how to trigger one tween at some point during another and call a function, I’ve played with calling functions as higher order things etc… what I want is to build a simple, ‘engine’ if you will, that lets me pre-script a whole bunch of actions for the title screen such that it “runs itself”.

This will also get massively reused elsewhere in the game.

Ta!