Created
March 20, 2021 18:29
-
-
Save weshardee/c04693dae3c79ffb8b0cfbeb49a52eff to your computer and use it in GitHub Desktop.
testing odin language server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package test | |
| import "core:math/linalg" | |
| import "core:math" | |
| import "core:fmt" | |
| import "core:container" | |
| import "src:lib" | |
| import "src:lib/core" | |
| import "src:lib/draw" | |
| import "src:lib/debug" | |
| import "src:lib/input" | |
| import "src:lib/shapes" | |
| V2 :: core.V2; | |
| V3 :: core.V3; | |
| M4 :: core.M4; | |
| VIEW_W :: 256; | |
| VIEW_H :: 240; | |
| PIXEL_SCALE :: 3; | |
| INVERSE_SQRT_TWO :: 1 / math.SQRT_TWO; | |
| PIG_RGBA :: #load("res/pig.rgba"); | |
| PIG_W :: 96; | |
| PIG_H :: 24; | |
| PIG_FRAME_W :: PIG_W / 3; | |
| PIG_RADIUS :: 8; | |
| PIG_Y_OFFSET :: 8; | |
| LAUNCH_BUTTON_RGBA :: #load("res/LaunchButton.rgba"); | |
| LAUNCH_BUTTON_W :: 48; | |
| LAUNCH_BUTTON_H :: 16; | |
| LAUNCH_BUTTON_SIZE :: V2{LAUNCH_BUTTON_W, LAUNCH_BUTTON_H}; | |
| ROCKET_SHIP_RGBA :: #load("res/RocketShip.rgba"); | |
| ROCKET_SHIP_W :: 64; | |
| ROCKET_SHIP_H :: 96; | |
| ROCKET_SHIP_OFFSET_X :: 32; | |
| ROCKET_SHIP_LAUNCH_RGBA :: #load("res/RocketShipLaunch.rgba"); | |
| ROCKET_SHIP_LAUNCH_W :: 64; | |
| ROCKET_SHIP_LAUNCH_H :: 128; | |
| ROCKET_SHIP_LAUNCH_OFFSET_Y :: ROCKET_SHIP_LAUNCH_H - ROCKET_SHIP_H; | |
| BTN_PAD :: 10; | |
| PIG_MOVE_SPEED :: 1; | |
| PIG_ANIM_SPEED :: 0.1; | |
| MAX_APPLES :: 128; | |
| APPLE_RGBA :: #load("res/apple.rgba"); | |
| APPLE_W :: 10; | |
| APPLE_H :: 12; | |
| APPLE_HALF_W :: APPLE_W / 2; | |
| APPLE_HALF_H :: APPLE_H / 2; | |
| APPLE_RADIUS :: 5; | |
| Pig :: struct { | |
| img_id : int, | |
| pos: V3, | |
| transform : M4, | |
| frames : [3]core.Quad_Corners, | |
| anim : f32, | |
| frame_i : int, | |
| state : Pig_State, | |
| facing_x : f32, | |
| area : shapes.Circle, | |
| } | |
| Apple :: struct { | |
| pos : V3, | |
| transform : M4, | |
| area : shapes.Circle, | |
| eaten : bool, | |
| }; | |
| Pig_State :: enum { | |
| Idle, | |
| Moving, | |
| } | |
| State :: struct { | |
| tick : f32, | |
| view_bottom_right : V3, | |
| launch_btn_id : int, | |
| launch_btn_corners : core.Quad_Corners, | |
| launch_btn_translate : V3, | |
| launch_btn_transform : M4, | |
| rocket_img_id : int, | |
| rocket_launch_img_id : int, | |
| rocket_corners : core.Quad_Corners, | |
| rocket_launch_corners : core.Quad_Corners, | |
| rocket_pos : V3, | |
| rocket_vel : V2, | |
| rocket_transform : M4, | |
| pig : Pig, | |
| apple_img_id : int, | |
| apple_corners : core.Quad_Corners, | |
| apples : container.Small_Array(MAX_APPLES, Apple), | |
| score : int, | |
| launched : bool, | |
| pos : V2, | |
| }; | |
| state :: proc() -> ^State { | |
| return cast(^State)lib.ctx().game_state.data; | |
| } | |
| @export | |
| conf :: proc(conf: ^core.Conf) { | |
| conf.title = "Heartbeast 1-bit"; | |
| conf.width = VIEW_W * PIXEL_SCALE; | |
| conf.height = VIEW_H * PIXEL_SCALE; | |
| } | |
| @export | |
| load :: proc() { | |
| lib.init_state(State); | |
| ctx := lib.ctx(); | |
| state := state(); | |
| state.launch_btn_id = ctx.register_img( | |
| raw_data(LAUNCH_BUTTON_RGBA), LAUNCH_BUTTON_W, LAUNCH_BUTTON_H, 4); | |
| state.launch_btn_corners = draw.corners(0, 0, LAUNCH_BUTTON_W, LAUNCH_BUTTON_H); | |
| state.rocket_img_id = lib.ctx().register_img( | |
| raw_data(ROCKET_SHIP_RGBA), ROCKET_SHIP_W, ROCKET_SHIP_H, 4); | |
| state.rocket_corners = draw.corners( | |
| -ROCKET_SHIP_OFFSET_X, | |
| 0, | |
| ROCKET_SHIP_W - ROCKET_SHIP_OFFSET_X, | |
| ROCKET_SHIP_H); | |
| state.rocket_launch_img_id = ctx.register_img( | |
| raw_data(ROCKET_SHIP_LAUNCH_RGBA), ROCKET_SHIP_LAUNCH_W, ROCKET_SHIP_LAUNCH_H, 4); | |
| state.rocket_launch_corners = draw.corners( | |
| -ROCKET_SHIP_OFFSET_X, | |
| -ROCKET_SHIP_LAUNCH_OFFSET_Y, | |
| ROCKET_SHIP_LAUNCH_W - ROCKET_SHIP_OFFSET_X, | |
| ROCKET_SHIP_H); | |
| { | |
| pig_frame_half_w : f32 = PIG_FRAME_W / 2; | |
| pig_frame_half_h : f32 = PIG_H / 2; | |
| state.pig.img_id = ctx.register_img( | |
| raw_data(PIG_RGBA), PIG_W, PIG_H, 4); | |
| x0 := -pig_frame_half_w; | |
| x1 := pig_frame_half_w; | |
| y0 : f32 = -PIG_Y_OFFSET; | |
| y1 := y0 + PIG_H; | |
| u_increment : f32 = 1.0/3.0; | |
| u0 : f32 = 0; | |
| u1 : f32 = u_increment; | |
| for i in 0..2 { | |
| state.pig.frames[i] = draw.corners( | |
| x0=x0, x1=x1, y0=y0, y1=y1, u0=u0, u1=u1, v0=0, v1=1); | |
| u0 = u1; | |
| u1 += u_increment; | |
| } | |
| state.pig.facing_x = 1; | |
| state.pig.area.r = PIG_RADIUS; | |
| } | |
| state.rocket_pos.y = -160; | |
| state.apple_img_id = ctx.register_img( | |
| raw_data(APPLE_RGBA), APPLE_W, APPLE_H, 4); | |
| state.apple_corners = draw.corners( | |
| -APPLE_HALF_W, -APPLE_HALF_H, APPLE_HALF_W, APPLE_HALF_H); | |
| add_apple(V3{10, 10, 0}); | |
| add_apple(V3{20, 10, 0}); | |
| add_apple(V3{20, -10, 0}); | |
| } | |
| @export | |
| update :: proc(dt: f32) { | |
| state := state(); | |
| state.tick += 1; | |
| lib.set_view_2d(240, 160, .MAIN); | |
| win_w := f32(lib.ctx().window.width); | |
| win_h := f32(lib.ctx().window.height); | |
| state.view_bottom_right = core.unproject(V3{win_w, win_h, 0}); | |
| state.launch_btn_translate.x = state.view_bottom_right.x - LAUNCH_BUTTON_W - BTN_PAD; | |
| state.launch_btn_translate.y = state.view_bottom_right.y + BTN_PAD + 0.5; | |
| state.launch_btn_transform = linalg.matrix4_translate(state.launch_btn_translate); | |
| if input.was_pressed(input.Mouse_Button.LEFT) { | |
| mouse_pos := input.mouse_pos(); | |
| launch_btn_shape := shapes.Rect{ | |
| min_x = state.launch_btn_translate.x, | |
| min_y = state.launch_btn_translate.y, | |
| max_x = state.launch_btn_translate.x + LAUNCH_BUTTON_W, | |
| max_y = state.launch_btn_translate.y + LAUNCH_BUTTON_H, | |
| }; | |
| if (shapes.test_overlap(V2{mouse_pos.x, mouse_pos.y}, launch_btn_shape)) { | |
| state.launched = true; | |
| } | |
| } | |
| if state.launched { | |
| state.rocket_vel.y += 0.05; | |
| state.rocket_pos.y += state.rocket_vel.y; | |
| } | |
| rocket_pos_floored := linalg.round(state.rocket_pos); | |
| state.rocket_transform = linalg.matrix4_translate(rocket_pos_floored); | |
| lib.prune(&state.apples, proc(apple: ^Apple) -> bool { | |
| return apple.eaten; | |
| }); | |
| input_dir := get_input_dir(); | |
| state.pig.pos.x += input_dir.x * PIG_MOVE_SPEED; | |
| state.pig.pos.y += input_dir.y * PIG_MOVE_SPEED; | |
| has_input := input_dir.x != 0 || input_dir.y != 0; | |
| if input_dir.x != 0 { | |
| state.pig.facing_x = input_dir.x > 0 ? 1 : -1; | |
| } | |
| switch state.pig.state { | |
| case .Idle: { | |
| if has_input { | |
| state.pig.anim = 1; | |
| state.pig.state = .Moving; | |
| } | |
| } | |
| case .Moving: { | |
| if !has_input { | |
| state.pig.state = .Idle; | |
| state.pig.anim = 0; | |
| } | |
| else { | |
| state.pig.anim += PIG_ANIM_SPEED; | |
| if state.pig.anim >= 3 do state.pig.anim -= 3; | |
| } | |
| } | |
| } | |
| state.pig.frame_i = cast(int)math.floor(state.pig.anim); | |
| state.pig.transform = linalg.mul( | |
| linalg.matrix4_translate(linalg.round(state.pig.pos)), | |
| linalg.matrix4_scale(core.V3{state.pig.facing_x, 1, 1}), | |
| ); | |
| state.pig.area.center = V2{state.pig.pos.x, state.pig.pos.y}; | |
| lib.each(&state.apples, check_if_eaten); | |
| } | |
| @export | |
| draw :: proc() { | |
| state := state(); | |
| draw.img( | |
| state.pig.img_id, | |
| state.pig.frames[state.pig.frame_i], | |
| state.pig.transform, | |
| ); | |
| pig_pos_v2 := V2{state.pig.pos.x, state.pig.pos.y}; | |
| draw.circ({ | |
| center = pig_pos_v2, | |
| r = PIG_RADIUS, | |
| }, draw.RED); | |
| draw.point(pig_pos_v2, draw.RED); | |
| draw.img( | |
| state.launch_btn_id, | |
| state.launch_btn_corners, | |
| state.launch_btn_transform, | |
| ); | |
| if state.launched { | |
| draw.img( | |
| state.rocket_launch_img_id, | |
| state.rocket_launch_corners, | |
| state.rocket_transform, | |
| ); | |
| } | |
| else { | |
| draw.img( | |
| state.rocket_img_id, | |
| state.rocket_corners, | |
| state.rocket_transform, | |
| ); | |
| } | |
| lib.each(&state.apples, draw_apple); | |
| } | |
| get_input_dir :: proc() -> V2 { | |
| if input.use_controller() { | |
| return input.l_stick(); | |
| } | |
| else { | |
| x, y : f32; | |
| if input.is_down(input.Key_Code.W) do y += 1; | |
| if input.is_down(input.Key_Code.A) do x -= 1; | |
| if input.is_down(input.Key_Code.S) do y -= 1; | |
| if input.is_down(input.Key_Code.D) do x += 1; | |
| if x != 0 && y != 0 { | |
| x *= INVERSE_SQRT_TWO; | |
| y *= INVERSE_SQRT_TWO; | |
| } | |
| return V2{x, y}; | |
| } | |
| } | |
| add_apple :: proc(pos: V3) { | |
| state := state(); | |
| transform := linalg.matrix4_translate(V3{pos.x, pos.y, 0}); | |
| container.small_array_push(&state.apples, Apple { | |
| pos = pos, | |
| transform = transform, | |
| area = shapes.Circle{center = V2{pos.x, pos.y}, r = APPLE_RADIUS}, | |
| }); | |
| } | |
| draw_apple :: proc(apple: ^Apple) { | |
| state := state(); | |
| draw.img( | |
| state.apple_img_id, | |
| state.apple_corners, | |
| apple.transform, | |
| ); | |
| draw.circ({ | |
| center = V2{apple.pos.x, apple.pos.y}, | |
| r = APPLE_RADIUS, | |
| }, draw.RED); | |
| } | |
| check_if_eaten :: proc(apple: ^Apple) { | |
| state := state(); | |
| if apple.eaten do return; | |
| if shapes.test_overlap(apple.area, state.pig.area) { | |
| apple.eaten = true; | |
| state.score += 1; | |
| // TODO play a sound | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment