color game

This commit is contained in:
me 2025-12-20 22:31:46 +02:00
parent b0b10ef54c
commit 01d49ff724
6 changed files with 112 additions and 22 deletions

View file

@ -1,5 +1,3 @@
let speed = 100
let setup = fn() {
return {
.color: {
@ -8,16 +6,18 @@ let setup = fn() {
.b: random_u8(),
},
.rect: {
.speed: 100,
.dimensions: {
.x: 100,
.y: 100,
.w: 100,
.h: 100,
.x: 50,
.y: 50,
.w: 300 - 50,
.h: 300 - 50,
},
.color: {
.r: random_u8(),
.g: random_u8(),
.b: random_u8(),
.speed: 150,
},
},
};
@ -25,19 +25,60 @@ let setup = fn() {
let update = 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,
# };
let movement = {
.x: input.gamepad1.sticks.left.x,
.y: input.gamepad1.sticks.left.y,
.x: dpad_x,
.y: dpad_y,
};
state.rect.dimensions.x =
state.rect.dimensions.x + (delta * speed * movement.x);
state.rect.dimensions.x + (delta * state.rect.speed * movement.x);
state.rect.dimensions.y =
state.rect.dimensions.y + (delta * speed * movement.y);
state.rect.dimensions.y + (delta * state.rect.speed * movement.y);
let color = {
.r: state.rect.color.r + (input.gamepad1.sticks.right.x * delta * state.rect.color.speed),
.g: state.rect.color.g + ((0 - input.gamepad1.sticks.right.y) * delta * state.rect.color.speed),
.b: state.rect.color.b + ((0 - input.gamepad1.sticks.left.y) * delta * state.rect.color.speed),
};
state.rect.color.r = if ((0 <= color.r) && (color.r <= 255)) { color.r } else { if color.r < 0 { 0 } else { 255 } };
state.rect.color.g = if ((0 <= color.g) && (color.g <= 255)) { color.g } else { if color.g < 0 { 0 } else { 255 } };
state.rect.color.b = if ((0 <= color.b) && (color.b <= 255)) { color.b } else { if color.b < 0 { 0 } else { 255 } };
return state;
}
let draw = fn(state) {
frame_clear(state.color.r, state.color.g, state.color.b);
draw_rectangle(state.rect.dimensions, state.rect.color);
let mut count = 0;
let r_diff = state.color.r - state.rect.color.r;
let g_diff = state.color.g - state.rect.color.g;
let b_diff = state.color.b - state.rect.color.b;
let epsilon = 2;
if ((0 - epsilon) < r_diff) && (r_diff < epsilon) { count = count + 1; };
if ((0 - epsilon) < g_diff) && (g_diff < epsilon) { count = count + 1; };
if ((0 - epsilon) < b_diff) && (b_diff < epsilon) { count = count + 1; };
if count == 0 {
draw_text("Match the colors", 200, 200, 50, { .r: 255, .g: 255, .b: 255 });
};
if count == 1 {
draw_text("Close", 200, 200, 50, { .r: 255, .g: 255, .b: 255 });
};
if count == 2 {
draw_text("Closer!!", 200, 200, 50, { .r: 255, .g: 255, .b: 255 });
};
if count == 3 {
draw_text("Great Job!", 200, 200, 50, { .r: 255, .g: 255, .b: 255 });
};
}

View file

@ -204,7 +204,11 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
state.variables.set(reference, rhs.clone());
Ok(rhs)
}
v => Err(Error::NotAReference(v.clone(), Backtrace::capture())),
v => Err(Error::NotAReference(
*lhs.clone(),
v.clone(),
Backtrace::capture(),
)),
},
ast::Op::Calc(cop) => {
let lhs = eval_expr(expr_env, state, lhs)?;
@ -378,7 +382,11 @@ fn eval_expr_shallow(
let result = expr_env.get(&var)?;
match result {
ast::Value::Ref(_) => Ok(result.clone()),
v => Err(Error::NotAReference(v.clone(), Backtrace::capture())),
v => Err(Error::NotAReference(
expr.clone(),
v.clone(),
Backtrace::capture(),
)),
}
}
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {

View file

@ -15,7 +15,7 @@ pub enum Error {
LastStatementNotAnExpr(Backtrace),
NotAFunction(ast::Expr, Backtrace),
NotARecord(ast::Value, Backtrace),
NotAReference(ast::Value, Backtrace),
NotAReference(ast::Expr, ast::Value, Backtrace),
NotABoolean(ast::Value, Backtrace),
OpError(ast::Value, ast::Op, ast::Value, Backtrace),
MigrationError(ast::Value, String, Backtrace),
@ -33,7 +33,9 @@ impl PartialEq for Error {
(Error::NotAFunction(a1, _), Error::NotAFunction(a2, _)) => a1 == a2,
(Error::NotARecord(a1, _), Error::NotARecord(a2, _)) => a1 == a2,
(Error::NotAReference(a1, _), Error::NotAReference(a2, _)) => a1 == a2,
(Error::NotAReference(a1, b1, _), Error::NotAReference(a2, b2, _)) => {
a1 == a2 && b1 == b2
}
(Error::NotABoolean(a1, _), Error::NotABoolean(a2, _)) => a1 == a2,
(Error::MigrationError(a1, b1, _), Error::MigrationError(a2, b2, _)) => {
a1 == a2 && b1 == b2
@ -62,7 +64,10 @@ impl std::fmt::Display for Error {
}
Error::NotAFunction(a, b) => write!(f, "Not a function {a:?}\n{b}"),
Error::NotARecord(a, b) => write!(f, "Not a record {a:?}\n{b}"),
Error::NotAReference(a, b) => write!(f, "Not a reference {a:?}\n{b}"),
Error::NotAReference(a, b, c) => write!(
f,
"Not a reference. Are you missing a `mut`? {a:?} {b:?}\n{c}"
),
Error::NotABoolean(a, b) => write!(f, "Not a boolean {a:?}\n{b}"),
Error::ArgumentsMismatch(a) => write!(f, "Arguments mismatch\n{a}"),
Error::OpError(a, b, c, d) => write!(f, "Op Error {a:?} {b:?} {c:?}\n{d}"),

View file

@ -5,8 +5,8 @@ fn window_conf() -> Conf {
Conf {
window_title: "Ayin".to_owned(),
fullscreen: false,
window_width: SCREEN_WIDTH,
window_height: SCREEN_HEIGHT,
window_width: SCREEN_WIDTH as i32,
window_height: SCREEN_HEIGHT as i32,
..Default::default()
}
}
@ -15,6 +15,9 @@ fn window_conf() -> Conf {
async fn main() {
env_logger::init();
info!("Hello, 👁️‍🗨️!");
if screen_width() < SCREEN_WIDTH {
request_new_screen_size(SCREEN_WIDTH as f32, SCREEN_HEIGHT as f32);
}
let args: Vec<String> = std::env::args().collect();
let file = args[1].clone();

View file

@ -1,14 +1,16 @@
use macroquad::prelude as mq;
use macroquad::time::get_frame_time;
use rand::prelude::*;
use crate::ast;
use crate::interpret::PrimitiveFuncs;
use macroquad::prelude as mq;
use crate::runtime::types::SCALE;
pub fn primitive_funcs() -> PrimitiveFuncs {
PrimitiveFuncs::new(vec![
("frame_clear", clear),
("draw_rectangle", draw_rectangle),
("draw_text", draw_text),
("get_frame_time", frame_time),
("random_u8", random_u8),
])
@ -58,7 +60,31 @@ fn draw_rectangle(args: Vec<ast::Expr>) -> ast::Value {
}
_ => todo!(),
};
mq::draw_rectangle(rectangle.x, rectangle.y, rectangle.w, rectangle.h, color);
mq::draw_rectangle(
rectangle.x * SCALE as f32,
rectangle.y * SCALE as f32,
rectangle.w * SCALE as f32,
rectangle.h * SCALE as f32,
color,
);
ast::UNIT_VALUE
}
fn draw_text(args: Vec<ast::Expr>) -> ast::Value {
let text = to_string(args.get(0));
let x = to_f32(args.get(1));
let y = to_f32(args.get(2));
let size = to_f32(args.get(3));
let color = match args.get(4) {
Some(ast::Expr::Record(record)) => {
let r = to_u8(record.get(&"r".into()));
let g = to_u8(record.get(&"g".into()));
let b = to_u8(record.get(&"b".into()));
mq::Color::from_rgba(r, g, b, 255)
}
_ => todo!(),
};
mq::draw_text(&text, x, y, size, color);
ast::UNIT_VALUE
}
@ -79,3 +105,10 @@ fn to_f32(value: Option<&ast::Expr>) -> f32 {
_ => 0.0,
}
}
fn to_string(value: Option<&ast::Expr>) -> String {
match value {
Some(ast::Expr::Value(ast::Value::String(s))) => s.clone(),
_ => "".into(),
}
}

View file

@ -90,7 +90,7 @@ pub struct Menu {
pub menu: bool,
}
pub const SCALE: i32 = 1;
pub const SCALE: f32 = 2.0;
pub const SCREEN_WIDTH: i32 = 360 * SCALE;
pub const SCREEN_HEIGHT: i32 = 360 * SCALE;
pub const SCREEN_WIDTH: f32 = 360.0 * SCALE;
pub const SCREEN_HEIGHT: f32 = 360.0 * SCALE;