diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-02-01 20:57:55 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-02-01 21:38:34 +0100 |
| commit | e86852857bc6f6ca1e1cd81db494071c5d9e3ff1 (patch) | |
| tree | 71f111699dd0d7526dbe5ee334c477db6e0362e0 /pong | |
| parent | e9ce94d72e1e8e51b7843b414504a07e132813e1 (diff) | |
| parent | fd4868df1fd24c05bce5c92cf8289fa755f25875 (diff) | |
| download | sylt-e86852857bc6f6ca1e1cd81db494071c5d9e3ff1.tar.gz | |
Merge branch 'main' into vectors
Diffstat (limited to 'pong')
| -rw-r--r-- | pong/Cargo.toml | 16 | ||||
| -rw-r--r-- | pong/README | 37 | ||||
| -rw-r--r-- | pong/pong.tdy | 199 | ||||
| -rw-r--r-- | pong/src/main.rs | 90 |
4 files changed, 342 insertions, 0 deletions
diff --git a/pong/Cargo.toml b/pong/Cargo.toml new file mode 100644 index 0000000..acf7d67 --- /dev/null +++ b/pong/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "pong" +version = "0.1.0" +authors = ["Gustav Sörnäs <gustav@sornas.net>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +lto = "thin" + +[dependencies] +tihdy = { path = ".."} +tihdy_derive = { path = "../tihdy_derive" } + +macroquad = "0.2" diff --git a/pong/README b/pong/README new file mode 100644 index 0000000..be718ec --- /dev/null +++ b/pong/README @@ -0,0 +1,37 @@ +PONG +==== + +Made for Global Game Jam 2021 at LiU Game Jam's site. + +The language wasn't really ready for a normal game so we wanted to make Pong +(the easiest game we could think of) while fixing what we needed to make it +work. + +Building +-------- + +Clone the entire tihdy-repo, cd into the pong-directory and then cargo run. + +Modifying +--------- + +All game logic is located in pong.tdy. Most of the configuration should be +straight forward. If you want to modify the controls, you need to change both +the string passed from pong.tdy as well as the respective function in src/main.rs +(key_down). + +If you want to add more rust functions (for example, to draw text to the screen) +you need to add it like the already existing functions. All functions need a +return type and a return value, even if it is a Type::Void and Value::Nil. (See +e.g. clear for an example.) For a draw_text you probably want to take a +Value::String(s), Value::Float(x), Value::Float(y) and so on. Inside the block +you then write your normal Rusty code. + +After writing your function you also need to link it so you can use it from the +game file. Add it to 'functions' like the other linked functions inside main() +in src/main.rs. + +After linking, the only thing left to do is call it from the game logic. You'll +get a type error if you pass the wrong parameters. Additional parameter +combinations can be set (much like normal function overloading) should you have +the need by adding more "arms" to the extern_function!(). diff --git a/pong/pong.tdy b/pong/pong.tdy new file mode 100644 index 0000000..15998f3 --- /dev/null +++ b/pong/pong.tdy @@ -0,0 +1,199 @@ +PADDLE_W := 0.5 +PADDLE_H := 3.0 + +blob Paddle { + x: float + y: float +} + +BALL_S := 0.4 +BALL_STARTV := 5.0 + +blob Ball { + x: float + y: float + + vx: float + vy: float +} + +blob Player { + paddle: Paddle + score: float +} + +blob State { + p1: Player + p2: Player + ball: Ball +} + +ball_speed := 2.0 +SPEED := 10.0 + +abs := fn a: float -> float { + if a < 0.0 { + ret -a + } + ret a +} + +and := fn a: bool, b: bool -> bool { + if a { + ret b + } + ret false +} + +or := fn a: bool, b: bool -> bool { + if a { + ret true + } + ret b +} + +sign := fn a: float -> float { + if a < 0.0 { + ret -1.0 + } + ret 1.0 +} + +rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: float, bw: float, bh: float -> bool { + acx := ax + aw / 2. + acy := ay + ah / 2. + + bcx := bx + bw / 2. + bcy := by + bh / 2. + + dx := abs(acx - bcx) + (-aw - bw) / 2. + dy := abs(acy - bcy) + (-ah - bh) / 2. + ret and(dx < 0., dy < 0.) +} + +ball_and_paddle_check := fn pad: Paddle, ball: Ball { + + if rect_overlap(ball.x, ball.y, BALL_S, BALL_S, pad.x, pad.y, PADDLE_W, PADDLE_H) { + SPEEDUP := 0.5 + ballcy := ball.y + BALL_S / 2. + padcy := pad.y + PADDLE_H / 2. + if ball.x < pad.x { + ball.vx = -abs(ball.vx) - SPEEDUP + ball.vy = ball.vy + (ballcy - padcy) * 3. + } else { + ball.vx = abs(ball.vx) + SPEEDUP + ball.vy = ball.vy + (ballcy - padcy) * 3. + } + } +} + +update := fn state: State { + delta := get_delta() + speed := delta * SPEED + + if key_down("w") { + state.p1.paddle.y = state.p1.paddle.y - speed + } + if key_down("s") { + state.p1.paddle.y = state.p1.paddle.y + speed + } + + if state.p1.paddle.y < 0.0 { + state.p1.paddle.y = 0.0 + } + + if state.p1.paddle.y > 20.0 - PADDLE_H { + state.p1.paddle.y = 20.0 - PADDLE_H + } + + if key_down("i") { + state.p2.paddle.y = state.p2.paddle.y - speed + } + if key_down("k") { + state.p2.paddle.y = state.p2.paddle.y + speed + } + + if state.p2.paddle.y < 0.0 { + state.p2.paddle.y = 0.0 + } + + if state.p2.paddle.y > 20.0 - PADDLE_H { + state.p2.paddle.y = 20.0 - PADDLE_H + } + + state.ball.x = state.ball.x + delta * state.ball.vx + state.ball.y = state.ball.y + delta * state.ball.vy + + if state.ball.y < 0. { + state.ball.vy = abs(state.ball.vy) + } + + if state.ball.y > 20. - 0.2 { + state.ball.vy = -abs(state.ball.vy) + } + + if state.ball.x < 0.0 { + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = -BALL_STARTV + state.ball.vy = 0. + state.p1.score = state.p1.score + 1.0 + } + + if state.ball.x > 20.0 { + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = BALL_STARTV + state.ball.vy = 0. + state.p2.score = state.p2.score + 1.0 + } + + ball_and_paddle_check(state.p1.paddle, state.ball) + ball_and_paddle_check(state.p2.paddle, state.ball) +} + +draw := fn state: State { + clear() + + draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, PADDLE_W, PADDLE_H) + draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, PADDLE_W, PADDLE_H) + + for y := 0.0, y < state.p1.score, y = y + 1.0 { + draw_rectangle(15.0, y * 0.5, 0.5, 0.5) + } + + for y := 0.0, y < state.p2.score, y = y + 1.0 { + draw_rectangle(5.0, y * 0.5, 0.5, 0.5) + } + + draw_rectangle(state.ball.x, state.ball.y, BALL_S, BALL_S) +} + +init := fn { + state := State() + state.ball = Ball() + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = BALL_STARTV + state.ball.vy = 0.0 + + state.p1 = Player() + state.p1.score = 0.0 + state.p1.paddle = Paddle() + state.p1.paddle.x = 1. + state.p1.paddle.y = 10. + + state.p2 = Player() + state.p2.score = 0.0 + state.p2.paddle = Paddle() + state.p2.paddle.x = 19. + state.p2.paddle.y = 10. + + for i := 0, i == i, i = i + 1 { + update(state) + draw(state) + yield + } +} + +init() diff --git a/pong/src/main.rs b/pong/src/main.rs new file mode 100644 index 0000000..2ab4b4a --- /dev/null +++ b/pong/src/main.rs @@ -0,0 +1,90 @@ +use macroquad::{Camera2D, DARKPURPLE, KeyCode, SKYBLUE, clear_background, draw_rectangle, get_frame_time, is_key_down, next_frame, set_camera, vec2}; +use std::path::Path; +use tihdy::{Type, Value}; +use tihdy::vm::OpResult; +use tihdy_derive::extern_function; + +const SCREEN_WIDTH: f32 = 20.0; +const SCREEN_HEIGHT: f32 = 20.0; + +extern_function!(log + [Value::Float(f1), Value::Float(f2)] -> Type::Void => { + println!("({}, {})", f1, f2); + Ok(Value::Nil) + }, +); + +extern_function!(get_delta + [] -> Type::Float => { + Ok(Value::Float(get_frame_time() as f64)) + }, +); + +extern_function!(key_down + [Value::String(s)] -> Type::Bool => { + let s: &str = s; + Ok(Value::Bool(match s { + "w" => is_key_down(KeyCode::W), + "s" => is_key_down(KeyCode::S), + "i" => is_key_down(KeyCode::I), + "k" => is_key_down(KeyCode::K), + _ => false, + })) + }, +); + +extern_function!(my_draw_rectangle + [Value::Float(x), Value::Float(y), Value::Float(w), Value::Float(h)] -> Type::Void => { + draw_rectangle(*x as f32, *y as f32, *w as f32, *h as f32, DARKPURPLE); + Ok(Value::Nil) + }, +); + +extern_function!(clear + [] -> Type::Void => { + clear_background(SKYBLUE); + Ok(Value::Nil) + }, +); + +#[macroquad::main("Pong")] +async fn main() { + + let functions: Vec<(String, tihdy::RustFunction)> = vec![ + ("log".to_string(), log), + ("get_delta".to_string(), get_delta), + ("key_down".to_string(), key_down), + ("draw_rectangle".to_string(), my_draw_rectangle), + ("clear".to_string(), clear), + ]; + + let vm = tihdy::compile_file(Path::new("pong.tdy"), false, functions); + if let Err(errs) = vm { + for err in errs { + println!("{}", err); + } + return; + } + + set_camera(Camera2D { + zoom: vec2(1. / SCREEN_WIDTH * 2., -1. / SCREEN_HEIGHT * 2.), + target: vec2(SCREEN_WIDTH / 2., SCREEN_HEIGHT / 2.), + ..Default::default() + }); + + let mut vm = vm.unwrap(); + loop { + match vm.run() { + Err(e) => { + println!("{:?}", e); + break; + } + Ok(OpResult::Yield) => { + next_frame().await + } + _ => { + break; + } + } + } +} |
