use criterion::{Criterion, criterion_group, criterion_main}; use std::hint::black_box; fn criterion_benchmark(c: &mut Criterion) { c.bench_function("minimal", |b| { b.iter(|| { let program = " let main = fn() { 1 } "; ayin::run_main(black_box(program)) }) }); c.bench_function("game", |b| { b.iter(|| { let program = " let main = fn() { setup() } let screen_size = 360 let shoot_timer = 90 let shot_timer = 1 let dim = { .w: 32, .h: 32, } let bullet_dim = { .w: dim.w / 4, .h: dim.h / 4, } let migrate = fn(state) { state } let setup = fn() { return { .player: { .pos: { .x: (screen_size - dim.w) - dim.w, .y: dim.h * 5, }, .speed: 220, .shot: 1, .shot_timer: 0, }, .opponent: { .pos: { .x: dim.w, .y: dim.h, }, .speed: 60, .timer: 0, }, .bullets: { .pos: { .x: -20, .y: -20, }, .movement: { .x: 0, .y: 0, }, .speed: 180, }, .timer: 0, .status: \"ongoing\", } } let move_player = fn(state, input) { let delta = get_frame_time() let dpad_x = if input.gamepad1.dpad.right { 1 } else { 0 } + if input.gamepad1.dpad.left { -1 } else { 0 } let dpad_y = if input.gamepad1.dpad.down { 1 } else { 0 } + if input.gamepad1.dpad.up { -1 } else { 0 } let movement = { .x: input.gamepad1.sticks.left.x + dpad_x, .y: input.gamepad1.sticks.left.y + dpad_y, } state.player.pos.x = max(0, min( state.player.pos.x + ((delta * state.player.speed * movement.x) / state.player.shot) , screen_size - dim.w ) ) state.player.pos.y = max(0, min( state.player.pos.y + ((delta * state.player.speed * movement.y) / state.player.shot) , screen_size - dim.w ) ) } let move_opponent = fn(state) { let delta = get_frame_time() let opponent_movement = { .x: if abs(state.opponent.pos.x - state.player.pos.x) < 5 { 0 } else { if state.opponent.pos.x < state.player.pos.x { 1 } else { -1 } }, .y: if abs(state.opponent.pos.y - state.player.pos.y) < 5 { 0 } else { if state.opponent.pos.y < state.player.pos.y { 1 } else { -1 } }, } state.opponent.pos.x = max(0, min( state.opponent.pos.x + (delta * state.opponent.speed * opponent_movement.x) , screen_size - dim.w ) ) state.opponent.pos.y = max(0, min( state.opponent.pos.y + (delta * state.opponent.speed * opponent_movement.y) , screen_size - dim.w ) ) shoot_bullets(state, opponent_movement) } let shoot_bullets = fn(state, opponent_movement) { let delta = get_frame_time() state.opponent.timer = state.opponent.timer - 1 if (state.opponent.timer <= 0) && (state.status != \"caught\") { state.opponent.timer = shoot_timer state.bullets.pos.x = state.opponent.pos.x + (dim.w * opponent_movement.x) state.bullets.pos.y = state.opponent.pos.y + (dim.h * opponent_movement.y) state.bullets.movement.x = opponent_movement.x state.bullets.movement.y = opponent_movement.y } } let move_bullets = fn(state) { let delta = get_frame_time() state.bullets.pos.x = state.bullets.pos.x + (delta * state.bullets.speed * state.bullets.movement.x) state.bullets.pos.y = state.bullets.pos.y + (delta * state.bullets.speed * state.bullets.movement.y) } let update = fn(state, input) { let delta = get_frame_time() if state.status != \"caught\" { state.timer = state.timer + delta } if state.status == \"ongoing\" { move_player(state, input) } if state.player.shot_timer > 0 { state.player.shot_timer = state.player.shot_timer - delta } else { state.player.shot_timer = 0 } move_opponent(state) move_bullets(state) if is_touching(make_rect(state.bullets.pos, { .w: dim.w / 2, .h: dim.h / 2 }), make_rect(state.player.pos, dim)) && (state.player.shot_timer == 0) { state.player.shot = state.player.shot + 1 state.player.shot_timer = shot_timer } if is_touching(make_rect(state.opponent.pos, dim), make_rect(state.player.pos, dim)) { state.status = \"caught\" } if input.gamepad1.buttons.y { let new_state = setup() state.player = new_state.player state.opponent = new_state.opponent state.bullets = new_state.bullets state.status = new_state.status state.timer = new_state.timer } state } let draw = fn(state) { frame_clear(0, 0, 0) let player_rect = { .x: state.player.pos.x, .y: state.player.pos.y, .w: dim.w, .h: dim.h, } let color = { .r: 105 + (state.player.shot_timer * 100), .g: 225, .b: 125 } draw_rectangle(player_rect, color) let opponent_rect = { .x: state.opponent.pos.x, .y: state.opponent.pos.y, .w: dim.w, .h: dim.h, } let color = { .r: 255, .g: 155, .b: 255 - (state.player.shot_timer * 50) } draw_rectangle(opponent_rect, color) let bullet_rect = { .x: state.bullets.pos.x, .y: state.bullets.pos.y, .w: bullet_dim.w, .h: bullet_dim.h, } let color = { .r: 255, .g: 135, .b: 225 } draw_rectangle(bullet_rect, color) if state.status == \"caught\" { draw_text(\"You got caught <3\", 20, 20, 20, { .r: 155, .g: 55, .b: 255 }) } else { draw_text(\"There she is!\", 40, 20, 20, { .r: 255, .g: 55, .b: 155 }) if state.player.shot_timer > 0 { draw_text(\"<3\", 200, 20, 20, { .r: 100 + (state.player.shot_timer * 50 * state.player.shot) % 255, .g: 100, .b: 100, }) } } draw_text(state.timer, 260, 20, 20, { .r: 55, .g: 205, .b: 155 }) } let min = fn(a,b) { if a < b { a } else { b } } let max = fn(a,b) { if a < b { b } else { a } } let abs = fn(a) { if a >= 0 { a } else { 0 - a } } let make_rect = fn(pos, dim) { { .x: pos.x, .y: pos.y, .w: dim.w, .h: dim.h, } } let is_touching = fn(rect1, rect2) { if (((rect1.x < rect2.x) && ((rect1.x + rect1.w) > rect2.x)) && ((rect1.y < rect2.y) && ((rect1.y + rect1.h) > rect2.y))) || (((rect2.x < rect1.x) && ((rect2.x + rect2.w) > rect1.x)) && ((rect2.y < rect1.y) && ((rect2.y + rect2.h) > rect1.y))) { true } else { false } } "; ayin::run_main(black_box(program)) }) }); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches);