package snake import k2 "../.." import "core:math" import "core:fmt" import "core:time" import "core:math/rand" import "base:intrinsics" import "core:log" import "core:mem" WINDOW_SIZE :: 1000 GRID_WIDTH :: 20 CELL_SIZE :: 16 CANVAS_SIZE :: GRID_WIDTH*CELL_SIZE TICK_RATE :: 0.13 Vec2i :: [2]int MAX_SNAKE_LENGTH :: GRID_WIDTH*GRID_WIDTH snake: [MAX_SNAKE_LENGTH]Vec2i snake_length: int tick_timer: f32 = TICK_RATE move_direction: Vec2i game_over: bool food_pos: Vec2i place_food :: proc() { occupied: [GRID_WIDTH][GRID_WIDTH]bool for i in 0.. 0 { random_cell_index := rand.int31_max(i32(len(free_cells))) food_pos = free_cells[random_cell_index] } } restart :: proc() { start_head_pos := Vec2i { GRID_WIDTH / 2, GRID_WIDTH / 2 } snake[0] = start_head_pos snake[1] = start_head_pos - {0, 1} snake[2] = start_head_pos - {0, 2} snake_length = 3 move_direction = {0, 1} game_over = false place_food() } main :: proc() { context.logger = log.create_console_logger() when ODIN_DEBUG { track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) context.allocator = mem.tracking_allocator(&track) defer { if len(track.allocation_map) > 0 { for _, entry in track.allocation_map { fmt.eprintf("%v leaked: %v bytes\n", entry.location, entry.size) } } mem.tracking_allocator_destroy(&track) } } k2.init(WINDOW_SIZE, WINDOW_SIZE, "Snake") SHADER_SOURCE :: #load("shader.hlsl") shader := k2.load_shader(string(SHADER_SOURCE), { .RG_32_Float, .RG_32_Float, .RGBA_8_Norm, .RG_32_Float, }) prev_time := time.now() restart() food_sprite := k2.load_texture_from_file("food.png") head_sprite := k2.load_texture_from_file("head.png") body_sprite := k2.load_texture_from_file("body.png") tail_sprite := k2.load_texture_from_file("tail.png") food_eaten_at := time.now() started_at := time.now() for !k2.shutdown_wanted() { time_now := time.now() dt := f32(time.duration_seconds(time.diff(prev_time, time_now))) prev_time = time_now total_time := time.duration_seconds(time.diff(started_at, time_now)) k2.process_events() if k2.key_is_held(.Up) { move_direction = {0, -1} } if k2.key_is_held(.Down) { move_direction = {0, 1} } if k2.key_is_held(.Left) { move_direction = {-1, 0} } if k2.key_is_held(.Right) { move_direction = {1, 0} } if game_over { if k2.key_went_down(.Enter) { restart() } } else { tick_timer -= dt } if tick_timer <= 0 { next_part_pos := snake[0] snake[0] += move_direction head_pos := snake[0] if head_pos.x < 0 || head_pos.y < 0 || head_pos.x >= GRID_WIDTH || head_pos.y >= GRID_WIDTH { game_over = true } for i in 1.. 1 { k2.override_shader_input(shader, 3, k2.Vec2{f32(math.cos(total_time*100)*4), f32(math.sin(total_time*120 + 3)*4)}) } k2.draw_texture(food_sprite, {f32(food_pos.x), f32(food_pos.y)}*CELL_SIZE) k2.override_shader_input(shader, 3, nil) for i in 0..