package draw import "core:log" import "core:image" import "core:image/qoi" import sg "shared:sokol/gfx" Sprite :: struct { image: sg.Image, anim: Animation, active_anim: u32, frame_time: f32, current_frame: i32, width: i32, height: i32, pos: Vec2, offset: Vec2, scale: Vec2, } init_sprite :: proc( sprite: ^Sprite, path: string, anim: Animation = {}, ) -> bool { img, img_err := qoi.load_from_file(path) if img_err != nil { log.error("could not load image") return false } defer image.destroy(img) sprite.image = sg.make_image({ width = i32(img.width), height = i32(img.height), data = { mip_levels = { 0 = {ptr=&img.pixels.buf[0], size=len(img.pixels.buf)}, }, }, }) sprite.anim = anim sprite.width = i32(img.width / len(sprite.anim.frames)) sprite.height = i32(img.height) sprite.scale = Vec2{1, 1} log.debugf( "loaded sprite '%v' %vx%v (%vx%v)", path, sprite.width, sprite.height, img.width, img.height, ) return true } set_sprite_active_tag :: proc(sprite: ^Sprite, tag_name: string) { sprite.active_anim = sprite.anim.frame_tags_indices[tag_name] } update_sprite :: proc(sprite: ^Sprite, dt: f32) { sprite.frame_time += dt tag := sprite.anim.frame_tags[sprite.active_anim] frame := sprite.anim.frames[sprite.current_frame] duration := f32(frame.duration) / 1000 if sprite.frame_time > duration { sprite.frame_time -= duration sprite.current_frame += 1 } if sprite.current_frame < tag.from { sprite.current_frame = tag.to } if sprite.current_frame > tag.to { sprite.current_frame = tag.from } } sprite :: proc( r: ^Renderer, sprite: Sprite, ) { frame := sprite.anim.frames[sprite.current_frame] texture( r, sprite.image, Rect { Vec2{f32(frame.rect.x), f32(frame.rect.y)}, Vec2{f32(frame.rect.w), f32(frame.rect.h)}, }, sprite.pos, sprite.offset, sprite.scale, ) }