Skip to content

Commit

Permalink
player can now move and function names stutter less
Browse files Browse the repository at this point in the history
  • Loading branch information
Acepie committed Apr 22, 2024
1 parent b4d5042 commit fec16b7
Show file tree
Hide file tree
Showing 9 changed files with 639 additions and 87 deletions.
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ target = "javascript"

[dependencies]
gleam_stdlib = ">= 0.36.0 and < 2.0.0"
p5js_gleam = ">= 1.0.1 and < 2.0.0"
p5js_gleam = ">= 2.0.0 and < 3.0.0"
prng = ">= 3.0.2 and < 4.0.0"
gleam_community_maths = ">= 1.1.0 and < 2.0.0"

Expand Down
8 changes: 4 additions & 4 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ packages = [
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
{ name = "gleam_javascript", version = "0.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "14D5B7E1A70681E0776BF0A0357F575B822167960C844D3D3FA114D3A75F05A8" },
{ name = "gleam_json", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "8B197DD5D578EA6AC2C0D4BDC634C71A5BCA8E7DB5F47091C263ECB411A60DF3" },
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
{ name = "glint", version = "0.18.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "BB0F14643CC51C069A5DC6E9082EAFCD9967AFD1C9CC408803D1A40A3FD43B54" },
{ name = "p5js_gleam", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "p5js_gleam", source = "hex", outer_checksum = "5DCFACE980EDE238BC81B8837C1A8DBE24B277B54B004B7BBCC6B8F473A9BDAD" },
{ name = "gleam_stdlib", version = "0.37.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5398BD6C2ABA17338F676F42F404B9B7BABE1C8DC7380031ACB05BBE1BCF3742" },
{ name = "glint", version = "0.18.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "5FB54D7732B4105E4AF4D89A7EE6D5E8CF33DA13A3575D0C6ECE470B97958454" },
{ name = "p5js_gleam", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "p5js_gleam", source = "hex", outer_checksum = "28CBB1EE158BB025B122E3BB33645B8C60FA4EB7BBDBE2A16E08C0A0638150FB" },
{ name = "prng", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_bitwise", "gleam_stdlib"], otp_app = "prng", source = "hex", outer_checksum = "C61B103F9AF5031ADAA35187CCE7130845EF5088D88FD084E5995D4FBEC9D745" },
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
{ name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" },
Expand All @@ -30,6 +30,6 @@ packages = [
esgleam = { version = ">= 0.6.0 and < 1.0.0" }
gleam_community_maths = { version = ">= 1.1.0 and < 2.0.0" }
gleam_stdlib = { version = ">= 0.36.0 and < 2.0.0" }
p5js_gleam = { version = ">= 1.0.1 and < 2.0.0" }
p5js_gleam = { version = ">= 2.0.0 and < 3.0.0"}
prng = { version = ">= 3.0.2 and < 4.0.0" }
startest = { version = ">= 0.2.0 and < 1.0.0" }
73 changes: 62 additions & 11 deletions src/bullet_heck_gleam.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import dungeon
import gleam/option
import p5js_gleam.{type P5, SketchConfig}
import p5js_gleam.{type P5}
import p5js_gleam/bindings as p5
import player
import vector
Expand All @@ -26,16 +25,68 @@ fn setup(p: P5) -> WorldState {

fn draw(p: P5, state: WorldState) {
p5.background(p, "#000000")
dungeon.draw_dungeon(p, state.dungeon)
player.draw_player(p, state.player)
dungeon.draw(p, state.dungeon)
player.draw(p, state.player)
}

fn on_key_pressed(key: String, _: Int, state: WorldState) -> WorldState {
case key {
" " -> GameRunning(..state, player: player.jump(state.player))
"w" ->
GameRunning(..state, player: player.accelerate_y(state.player, False))
"s" -> GameRunning(..state, player: player.accelerate_y(state.player, True))
"a" ->
GameRunning(..state, player: player.accelerate_x(state.player, False))
"d" -> GameRunning(..state, player: player.accelerate_x(state.player, True))
_ -> state
}
}

fn on_key_released(key: String, _: Int, state: WorldState) -> WorldState {
case key {
"w" | "s" -> GameRunning(..state, player: player.stop_y(state.player))
"a" | "d" -> GameRunning(..state, player: player.stop_x(state.player))
_ -> state
}
}

fn on_mouse_moved(x: Float, y: Float, state: WorldState) -> WorldState {
GameRunning(
..state,
player: player.look_toward(state.player, vector.Vector(x, y, 0.0)),
)
}

fn on_tick(state: WorldState) -> WorldState {
// Attempt to move player
let old_position = state.player.position
let moved = player.move(state.player)
let player = case
dungeon.can_move(state.dungeon, old_position, moved.position)
{
True -> moved
// If they can't move then just apply gravity
False ->
player.Player(
..state.player,
position: vector.Vector(
old_position.x,
old_position.y,
old_position.z +. state.player.velocity.z,
),
)
}

let player = player.update_velocity(player)
let player = player.apply_gravity(player)
GameRunning(..state, player: player)
}

pub fn main() {
p5.start_sketch(SketchConfig(
init: setup,
draw: draw,
on_tick: option.None,
on_key: option.None,
on_mouse: option.None,
))
p5js_gleam.create_sketch(init: setup, draw: draw)
|> p5js_gleam.set_on_key_pressed(on_key_pressed)
|> p5js_gleam.set_on_key_released(on_key_released)
|> p5js_gleam.set_on_mouse_moved(on_mouse_moved)
|> p5js_gleam.set_on_tick(on_tick)
|> p5.start_sketch
}
4 changes: 2 additions & 2 deletions src/dungeon.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,13 @@ fn compute_corner_walls(rooms: Rooms) -> Rooms {
}

/// Renders the dungeon to the screen.
pub fn draw_dungeon(p: P5, dungeon: Dungeon) {
pub fn draw(p: P5, dungeon: Dungeon) {
// rendering with shadows depends on order so we are using ranges
use col <- iterator.each(iterator.range(0, dungeon_size))
use row <- iterator.each(iterator.range(0, dungeon_size))
use r <- result.map(dict.get(dungeon.rooms, #(col, row)))

room.draw_room(p, r, col, row, room_size)
room.draw(p, r, col, row, room_size)
}

/// Get the coordinate that the given point is in.
Expand Down
112 changes: 105 additions & 7 deletions src/player.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,121 @@ pub fn new_player(initial_position: Vector) -> Player {

/// Advances the player forward assuming they can.
pub fn move(player: Player) -> Player {
Player(
..player,
position: vector.vector_add(player.position, player.velocity),
)
Player(..player, position: vector.add(player.position, player.velocity))
}

/// Accelerates the player's velocity.
pub fn update_velocity(player: Player) -> Player {
// Base acceleration
let vel = vector.vector_add(player.velocity, player.acceleration)
let vel = vector.add(player.velocity, player.acceleration)
// Limit xy velocity
let limited =
vector.vector_2d(vel)
|> vector.vector_limit(max_speed)
|> vector.limit(max_speed)
Player(..player, velocity: vector.Vector(limited.x, limited.y, vel.z))
}

/// Let's the player jump if they are on the ground.
pub fn jump(player: Player) -> Player {
case player.position.z, player.velocity.z {
p, v if p == 0.0 && v <=. 0.0 ->
Player(
..player,
velocity: vector.Vector(
player.velocity.x,
player.velocity.y,
jump_power,
),
)
_, _ -> player
}
}

/// Accelerates the player in the x direction.
pub fn accelerate_x(player: Player, forward: Bool) -> Player {
let acc = case forward {
True -> acceleration()
False -> -1.0 *. acceleration()
}
Player(
..player,
acceleration: vector.Vector(
acc,
player.acceleration.y,
player.acceleration.z,
),
)
}

/// Accelerates the player in the y direction.
pub fn accelerate_y(player: Player, forward: Bool) -> Player {
let acc = case forward {
True -> acceleration()
False -> -1.0 *. acceleration()
}
Player(
..player,
acceleration: vector.Vector(
player.acceleration.x,
acc,
player.acceleration.z,
),
)
}

/// Stops the player in the x direction.
pub fn stop_x(player: Player) -> Player {
Player(
..player,
velocity: vector.Vector(0.0, player.velocity.y, player.velocity.z),
acceleration: vector.Vector(
0.0,
player.acceleration.y,
player.acceleration.z,
),
)
}

/// Stops the player in the y direction.
pub fn stop_y(player: Player) -> Player {
Player(
..player,
velocity: vector.Vector(player.velocity.x, 0.0, player.velocity.z),
acceleration: vector.Vector(
player.acceleration.x,
0.0,
player.acceleration.z,
),
)
}

const player_gravity_strength = 0.02

// Applies gravity to the velocityy and resets z position to floor when appropriate.
pub fn apply_gravity(player: Player) -> Player {
let position = case player.position.z {
z if z <. 0.0 -> vector.Vector(player.position.x, player.position.y, 0.0)
_ -> player.position
}
Player(
..player,
position: position,
velocity: vector.Vector(
player.velocity.x,
player.velocity.y,
player.velocity.z -. player_gravity_strength,
),
)
}

/// Make player look towards a point.
pub fn look_toward(player: Player, point: Vector) -> Player {
Player(
..player,
firing_direction: vector.vector_2d(vector.subtract(point, player.position)),
)
}

/// Is the player currently dead.
pub fn is_player_dead(player: Player) -> Bool {
player.current_health <= 0
Expand All @@ -95,7 +193,7 @@ const player_fill_color = "#0000ff"
const player_stroke_color = "#000000"

/// Renders the player to the screen.
pub fn draw_player(p: P5, player: Player) {
pub fn draw(p: P5, player: Player) {
case is_player_dead(player), is_player_invulnerable(player) {
True, _ -> p5.fill(p, dead_fill_color)
_, True -> p5.fill(p, invulnerable_fill_color)
Expand Down
8 changes: 1 addition & 7 deletions src/room.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,7 @@ pub fn is_navigable(room: Room, direction: Direction) -> Bool {
}

/// Draws a room onto the screen at the given row and column.
pub fn draw_room(
p: P5,
room: Room,
room_column: Int,
room_row: Int,
room_size: Int,
) {
pub fn draw(p: P5, room: Room, room_column: Int, room_row: Int, room_size: Int) {
let top = int.to_float(room_row * room_size)
let bot = int.to_float({ room_row + 1 } * room_size)
let left = int.to_float(room_column * room_size)
Expand Down
40 changes: 20 additions & 20 deletions src/vector.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,68 +7,68 @@ pub type Vector {
}

/// Adds 2 vectors together.
pub fn vector_add(v1: Vector, v2: Vector) -> Vector {
pub fn add(v1: Vector, v2: Vector) -> Vector {
Vector(v1.x +. v2.x, v1.y +. v2.y, v1.z +. v2.z)
}

/// Subtracts the second vector from the first vector.
pub fn vector_subtract(v1: Vector, v2: Vector) -> Vector {
pub fn subtract(v1: Vector, v2: Vector) -> Vector {
Vector(v1.x -. v2.x, v1.y -. v2.y, v1.z -. v2.z)
}

/// Computes the dot product of 2 vectors.
pub fn vector_dot(v1: Vector, v2: Vector) -> Float {
pub fn dot(v1: Vector, v2: Vector) -> Float {
v1.x *. v2.x +. v1.y *. v2.y +. v1.z *. v2.z
}

/// Computes the cross product of 2 vectors.
pub fn vector_cross(v1: Vector, v2: Vector) -> Vector {
pub fn cross(v1: Vector, v2: Vector) -> Vector {
let yz = v1.y *. v2.z -. v1.z *. v2.y
let zx = v1.z *. v2.x -. v1.x *. v2.z
let xy = v1.x *. v2.y -. v1.y *. v2.x
Vector(yz, zx, xy)
}

/// Multiplies the vector by some value.
pub fn vector_multiply(v: Vector, mult: Float) -> Vector {
pub fn multiply(v: Vector, mult: Float) -> Vector {
Vector(v.x *. mult, v.y *. mult, v.z *. mult)
}

/// Divides the vector by some value.
pub fn vector_divide(v: Vector, mult: Float) -> Vector {
pub fn divide(v: Vector, mult: Float) -> Vector {
Vector(v.x /. mult, v.y /. mult, v.z /. mult)
}

/// Computes the square of the magnitude of the vector.
/// Mainly used for performance when computing square roots is unnecessary.
pub fn vector_magnitude_squared(v: Vector) -> Float {
pub fn magnitude_squared(v: Vector) -> Float {
v.x *. v.x +. v.y *. v.y +. v.z *. v.z
}

/// Computes the magnitude of the vector.
pub fn vector_magnitude(v: Vector) -> Float {
pub fn magnitude(v: Vector) -> Float {
// magnitude square is always positive
let assert Ok(mag) = float.square_root(vector_magnitude_squared(v))
let assert Ok(mag) = float.square_root(magnitude_squared(v))
mag
}

/// Computes a vector of the same heading with a magnitude of 1.
pub fn vector_normalize(v: Vector) -> Vector {
vector_divide(v, vector_magnitude(v))
pub fn normalize(v: Vector) -> Vector {
divide(v, magnitude(v))
}

/// Computes a vector of the same heading with maximum magnitude.
pub fn vector_limit(v: Vector, limit: Float) -> Vector {
pub fn limit(v: Vector, limit: Float) -> Vector {
let lim_squared = limit *. limit
case vector_magnitude_squared(v) {
case magnitude_squared(v) {
m if m <=. lim_squared -> v
_ -> vector_multiply(vector_normalize(v), limit)
_ -> multiply(normalize(v), limit)
}
}

/// Computes the distance between 2 vectors.
pub fn vector_distance(v1: Vector, v2: Vector) -> Float {
vector_magnitude(vector_subtract(v1, v2))
pub fn distance(v1: Vector, v2: Vector) -> Float {
magnitude(subtract(v1, v2))
}

/// Creates a 2d version of the vector.
Expand All @@ -77,7 +77,7 @@ pub fn vector_2d(v: Vector) -> Vector {
}

/// Computes the heading in radians of a vector.
pub fn vector_heading2d(v: Vector) -> Float {
pub fn heading2d(v: Vector) -> Float {
let res = elementary.atan2(v.y, v.x)
case res {
r if r <. 0.0 -> r +. 2.0 *. elementary.pi()
Expand All @@ -86,8 +86,8 @@ pub fn vector_heading2d(v: Vector) -> Float {
}

/// Rotates a vector around the z axis by the given amount in radians.
pub fn vector_rotate2d(v: Vector, rotation: Float) -> Vector {
let heading = vector_heading2d(v) +. rotation
let mag = vector_magnitude(vector_2d(v))
pub fn rotate2d(v: Vector, rotation: Float) -> Vector {
let heading = heading2d(v) +. rotation
let mag = magnitude(vector_2d(v))
Vector(elementary.cos(heading) *. mag, elementary.sin(heading) *. mag, v.z)
}
Loading

0 comments on commit fec16b7

Please sign in to comment.