diff --git a/assets/3rdparty/Swordsman_lvl3_Death_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Death_without_shadow.png new file mode 100644 index 0000000..e82ef4e Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Death_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_Hurt_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Hurt_without_shadow.png new file mode 100644 index 0000000..a95e8bb Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Hurt_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_Run_Attack_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Run_Attack_without_shadow.png new file mode 100644 index 0000000..58cad08 Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Run_Attack_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_Run_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Run_without_shadow.png new file mode 100644 index 0000000..fdb16f1 Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Run_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_Walk_Attack_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Walk_Attack_without_shadow.png new file mode 100644 index 0000000..69ed9d8 Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Walk_Attack_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_Walk_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_Walk_without_shadow.png new file mode 100644 index 0000000..82be044 Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_Walk_without_shadow.png differ diff --git a/assets/3rdparty/Swordsman_lvl3_attack_without_shadow.png b/assets/3rdparty/Swordsman_lvl3_attack_without_shadow.png new file mode 100644 index 0000000..675e81a Binary files /dev/null and b/assets/3rdparty/Swordsman_lvl3_attack_without_shadow.png differ diff --git a/assets/3rdparty/player_idle.png b/assets/3rdparty/player_idle.png new file mode 100644 index 0000000..45c2185 Binary files /dev/null and b/assets/3rdparty/player_idle.png differ diff --git a/assets/3rdparty/player_idle.png-autosave.kra b/assets/3rdparty/player_idle.png-autosave.kra new file mode 100644 index 0000000..1e9ff6f Binary files /dev/null and b/assets/3rdparty/player_idle.png-autosave.kra differ diff --git a/src3/gfx.odin b/src3/gfx.odin index e5af18c..59e1b1e 100644 --- a/src3/gfx.odin +++ b/src3/gfx.odin @@ -1,5 +1,6 @@ package main +import "core:fmt" import rl "vendor:raylib" Graphics :: union { @@ -8,6 +9,7 @@ Graphics :: union { GfxRect, GfxRing, GfxCircleLines, + GfxAnimatedSprite, GfxTexture, } @@ -38,11 +40,53 @@ GfxCircleLines :: struct { color: rl.Color, } -GfxTexture :: struct { +GfxTexture :: struct {} + +GfxAnimatedSprite :: struct { + pos: rl.Vector2, + rect: rl.Rectangle, + tex: ^rl.Texture2D, + frame: u32, + speed: f32, + current_time: f32, } -gfx_draw :: proc(pos: rl.Vector2, g: Graphics) { - #partial switch v in g { +PlayerTexFiles :: enum { + IDLE, + RUN, + RUN_ATTACK, + WALK, + WALK_ATTACK, + ATTACK, +} + + +GraphicsAssetStore :: struct { + playerTex: map[PlayerTexFiles]rl.Texture2D, +} + +gfx_get :: proc(g: ^GraphicsAssetStore, f: PlayerTexFiles) -> ^rl.Texture2D { + return &g.playerTex[f] +} + +gfx_init :: proc() -> GraphicsAssetStore { + st := GraphicsAssetStore{} + st.playerTex = make(map[PlayerTexFiles]rl.Texture2D) + + st.playerTex[.IDLE] = rl.LoadTexture("assets/3rdparty/player_idle.png") + + return st +} + +gfx_free :: proc(g: GraphicsAssetStore) { + for _, tex in g.playerTex { + rl.UnloadTexture(tex) + } + delete(g.playerTex) +} + +gfx_draw :: proc(pos: rl.Vector2, g: ^Graphics) { + #partial switch &v in g { case GfxCircle: rl.DrawCircleV(pos + v.pos, v.radius, v.color) case GfxRect: @@ -51,5 +95,30 @@ gfx_draw :: proc(pos: rl.Vector2, g: Graphics) { rl.DrawRing(pos + v.pos, v.inner_radius, v.outer_radius, 0, 360, 0, v.color) case GfxCircleLines: rl.DrawCircleLinesV(pos + v.pos, v.radius, v.color) + case GfxAnimatedSprite: + fmt.println(pos.x, pos.y) + //TODO: Count from L to R row-wize + v.rect.x = v.rect.width * f32(v.frame) + v.rect.y = v.rect.height * f32(v.frame) + rl.DrawTexturePro( + v.tex^, + v.rect, + rl.Rectangle { + pos.x - v.rect.width * 3 / 2, + pos.y - v.rect.height * 3 / 2, + v.rect.width * 3, + v.rect.height * 3, + }, + rl.Vector2{0, 0}, + 0, + rl.WHITE, + ) + v.current_time += rl.GetFrameTime() + if v.current_time > v.speed { + v.current_time = v.current_time - v.speed + v.frame += 1 + } + + // rl.DrawTextureRec(v.tex, v.rect, rl.Vector2{pos.x, pos.y}, rl.Color{}) } } diff --git a/src3/main.odin b/src3/main.odin index 844978c..45bc8b4 100644 --- a/src3/main.odin +++ b/src3/main.odin @@ -11,11 +11,14 @@ main :: proc() { rl.SetTargetFPS(TARGET_FPS) defer rl.CloseWindow() - camera := rl.Camera3D{ + gfx := gfx_init() + defer gfx_free(gfx) + + camera := rl.Camera3D { position = {0, 80, 80}, target = {0, 0, 0}, up = {0, 1, 0}, - fovy = 900, + fovy = 400, projection = .ORTHOGRAPHIC, } @@ -24,16 +27,16 @@ main :: proc() { state.collisions = make([dynamic]CollisionPair) defer delete(state.collisions) - state.player = spawn(state, make_player()) + state.player = spawn(state, make_player(&gfx)) - spawn(state, make_enemy({400, 300}, .Brute)) - spawn(state, make_enemy({-400, 200}, .Scout)) - spawn(state, make_enemy({300, -350}, .Grunt)) - spawn(state, make_enemy({-300, -300}, .Scout)) - spawn(state, make_enemy({100, 400}, .Grunt)) - spawn(state, make_enemy({-150, 350}, .Grunt)) - spawn(state, make_enemy({450, -150}, .Brute)) - spawn(state, make_enemy({-450, 100}, .Scout)) + // spawn(state, make_enemy({400, 300}, .Brute)) + // spawn(state, make_enemy({-400, 200}, .Scout)) + // spawn(state, make_enemy({300, -350}, .Grunt)) + // spawn(state, make_enemy({-300, -300}, .Scout)) + // spawn(state, make_enemy({100, 400}, .Grunt)) + // spawn(state, make_enemy({-150, 350}, .Grunt)) + // spawn(state, make_enemy({450, -150}, .Brute)) + // spawn(state, make_enemy({-450, 100}, .Scout)) for !rl.WindowShouldClose() { dt := rl.GetFrameTime() diff --git a/src3/player.odin b/src3/player.odin index 0b92e5b..e99f61e 100644 --- a/src3/player.odin +++ b/src3/player.odin @@ -43,13 +43,13 @@ Player :: struct { dash_timer: f32, } -make_player :: proc() -> Entity { +make_player :: proc(gfx: ^GraphicsAssetStore) -> Entity { p := Player { - level = 1, - xp = 0, - xp_next = 50, - base_dmg = 10, - base_crit = 0.1, + level = 1, + xp = 0, + xp_next = 50, + base_dmg = 10, + base_crit = 0.1, base_atk_cd = 0.35, base_max_hp = 100, attack_range = 90, @@ -62,7 +62,16 @@ make_player :: proc() -> Entity { } p.base.pos = {0, 0} p.base.col_size = 16 - p.base.gfx = {0 = GfxCircle{pos = {}, radius = 14, color = {80, 220, 100, 255}}} + p.base.gfx = { + 0 = GfxCircle{pos = {}, radius = 14, color = {80, 220, 100, 255}}, + 1 = GfxAnimatedSprite { + pos = {}, + rect = {0, 0, 64, 64}, + tex = gfx_get(gfx, .IDLE), + frame = 0, + speed = 1, + }, + } p.hp = p.base_max_hp p.max_hp = p.base_max_hp p.speed = 220 @@ -164,9 +173,9 @@ sys_input :: proc(state: ^GameState, dt: f32) { // движение (45° поворот под изометрию) move: rl.Vector2 - if rl.IsKeyDown(.W) || rl.IsKeyDown(.UP) do move += {-1, -1} - if rl.IsKeyDown(.S) || rl.IsKeyDown(.DOWN) do move += {1, 1} - if rl.IsKeyDown(.A) || rl.IsKeyDown(.LEFT) do move += {-1, 1} + if rl.IsKeyDown(.W) || rl.IsKeyDown(.UP) do move += {-1, -1} + if rl.IsKeyDown(.S) || rl.IsKeyDown(.DOWN) do move += {1, 1} + if rl.IsKeyDown(.A) || rl.IsKeyDown(.LEFT) do move += {-1, 1} if rl.IsKeyDown(.D) || rl.IsKeyDown(.RIGHT) do move += {1, -1} if p.dash_timer > 0 { @@ -195,16 +204,19 @@ sys_input :: proc(state: ^GameState, dt: f32) { if p.attack_timer > 0 do p.attack_timer -= dt if rl.IsMouseButtonPressed(.LEFT) && p.attack_timer <= 0 { p.attack_timer = player_atk_cd(p) - init_attack(state, Attack{ - parent = state.player, - dir = p.aim, - dmg = player_total_dmg(p), - crit = player_crit(p), - radius = p.attack_range, - arc = 1.3, - lifetime = player_atk_cd(p), - color = {255, 255, 255, 60}, - }) + init_attack( + state, + Attack { + parent = state.player, + dir = p.aim, + dmg = player_total_dmg(p), + crit = player_crit(p), + radius = p.attack_range, + arc = 1.3, + lifetime = player_atk_cd(p), + color = {255, 255, 255, 60}, + }, + ) } // навыки diff --git a/src3/scene.odin b/src3/scene.odin index 8a6a3c6..b81b20a 100644 --- a/src3/scene.odin +++ b/src3/scene.odin @@ -1,8 +1,8 @@ package main +import hm "core:container/handle_map" import "core:fmt" import math "core:math" -import hm "core:container/handle_map" import rl "vendor:raylib" SQRT2_INV :: 0.7071067811865476 @@ -120,11 +120,15 @@ entity_draw :: proc(state: ^GameState, e: ^Entity) { sp := rl.GetWorldToScreen({b.pos.x, 0, b.pos.y}, state.camera) scale := SCREEN_H / state.camera.fovy - #partial switch v in b.gfx[0] { - case GfxCircle: - rl.DrawCircleV(sp, v.radius * scale, v.color) - case: + for &g, _ in b.gfx { + gfx_draw(sp, &g) } + + // #partial switch v in b.gfx[0] { + // case GfxCircle: + // rl.DrawCircleV(sp, v.radius * scale, v.color) + // case: + // } } ground_effect_draw :: proc(state: ^GameState, e: ^Entity) { @@ -149,12 +153,7 @@ draw_arc_sector :: proc(pos: rl.Vector2, dir: rl.Vector2, radius: f32, arc: f32, a2 := start + arc * f32(i + 1) / f32(SEGMENTS) p1 := pos + rl.Vector2{math.cos_f32(a1), math.sin_f32(a1)} * radius p2 := pos + rl.Vector2{math.cos_f32(a2), math.sin_f32(a2)} * radius - rl.DrawTriangle3D( - {pos.x, 0.03, pos.y}, - {p1.x, 0.03, p1.y}, - {p2.x, 0.03, p2.y}, - color, - ) + rl.DrawTriangle3D({pos.x, 0.03, pos.y}, {p1.x, 0.03, p1.y}, {p2.x, 0.03, p2.y}, color) } }