Skip to content

Instantly share code, notes, and snippets.

@weshardee
Created March 20, 2021 18:29
Show Gist options
  • Save weshardee/c04693dae3c79ffb8b0cfbeb49a52eff to your computer and use it in GitHub Desktop.
Save weshardee/c04693dae3c79ffb8b0cfbeb49a52eff to your computer and use it in GitHub Desktop.
testing odin language server
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