Skip to content

Commit

Permalink
add ui and start and game over screens
Browse files Browse the repository at this point in the history
  • Loading branch information
Acepie committed May 1, 2024
1 parent d42e9a5 commit b32f60c
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 39 deletions.
Binary file added dist/fonts/Minecraftia-Regular.ttf
Binary file not shown.
Binary file added dist/fonts/WorkSans-Medium.ttf
Binary file not shown.
4 changes: 2 additions & 2 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ target = "javascript"

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

[dev-dependencies]
esgleam = ">= 0.6.0 and < 1.0.0"
startest = ">= 0.2.0 and < 1.0.0"
startest = ">= 0.2.1 and < 1.0.0"
20 changes: 11 additions & 9 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
{ name = "bigben", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "bigben", source = "hex", outer_checksum = "8E5A98FA6E981EEEF016C40F1CDFADA095927CAF6CAAA0C7E295EED02FC95947" },
{ name = "birl", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "976CFF85D34D50F7775896615A71745FBE0C325E50399787088F941B539A0497" },
{ name = "esgleam", version = "0.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "esgleam", source = "hex", outer_checksum = "571D149ACFB7C7A81CF8C7A70ECFDA5A084ADBF706962353C0DA85787CB4DD24" },
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
Expand All @@ -13,23 +14,24 @@ packages = [
{ name = "gleam_community_maths", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_maths", source = "hex", outer_checksum = "E30C61A75051DAF7CFD77C4FBAA04140FDA0B5D831955E7A74521E5576E2780D" },
{ 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.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.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "p5js_gleam", source = "hex", outer_checksum = "4EEC8FCD162486FCAA2AFEC9E8B7A8843AC9935551CF2B2A604A0F070AB6B00F" },
{ name = "prng", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_bitwise", "gleam_stdlib"], otp_app = "prng", source = "hex", outer_checksum = "C61B103F9AF5031ADAA35187CCE7130845EF5088D88FD084E5995D4FBEC9D745" },
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
{ name = "glint", version = "1.0.0-rc1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "91EC8EFA3E8FBCB842C219AA02E8072204CEE02597B4C36C2ED78AD86DD1B2EC" },
{ name = "p5js_gleam", version = "2.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "p5js_gleam", source = "hex", outer_checksum = "6280E50C5CF893BA84B6A2D82A3EA83BB764EA7F3509CA22BB12326D01283F85" },
{ name = "prng", version = "3.0.3", build_tools = ["gleam"], requirements = ["gleam_bitwise", "gleam_stdlib"], otp_app = "prng", source = "hex", outer_checksum = "53006736FE23A0F61828C95B505193E10905D8DB76E128F1642D3E571E08F589" },
{ 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" },
{ name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" },
{ name = "startest", version = "0.2.0", build_tools = ["gleam"], requirements = ["argv", "birl", "exception", "gleam_community_ansi", "gleam_erlang", "gleam_javascript", "gleam_stdlib", "glint", "simplifile", "tom"], otp_app = "startest", source = "hex", outer_checksum = "89F8575C91696D1713075F0B850A54160A32580A7CF415E045A0EEAD498AA30D" },
{ name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" },
{ name = "startest", version = "0.2.1", build_tools = ["gleam"], requirements = ["argv", "bigben", "birl", "exception", "gleam_community_ansi", "gleam_erlang", "gleam_javascript", "gleam_stdlib", "glint", "simplifile", "tom"], otp_app = "startest", source = "hex", outer_checksum = "D87A0C48712EE53878BBC5058FD4E74CD2B766779E6E7F72FC69D472C820C820" },
{ name = "thoas", version = "1.2.0", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "540C8CB7D9257F2AD0A14145DC23560F91ACDCA995F0CCBA779EB33AF5D859D1" },
{ name = "tom", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "0831C73E45405A2153091226BF98FB485ED16376988602CC01A5FD086B82D577" },
]

[requirements]
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 = ">= 2.1.1 and < 3.0.0"}
p5js_gleam = { version = ">= 2.1.2 and < 3.0.0"}
prng = { version = ">= 3.0.2 and < 4.0.0" }
startest = { version = ">= 0.2.0 and < 1.0.0" }
startest = { version = ">= 0.2.1 and < 1.0.0" }
189 changes: 161 additions & 28 deletions src/bullet_heck_gleam.gleam
Original file line number Diff line number Diff line change
@@ -1,120 +1,243 @@
import bullet
import dungeon
import gleam/bool
import gleam/int
import gleam/list
import p5js_gleam.{type P5}
import p5js_gleam.{type Assets, type P5}
import p5js_gleam/bindings as p5
import player
import utils
import vector

/// Represents the overall game state
type WorldState {
/// State of the world when the game is active
/// The start screen of the game.
StartScreen
/// State of the world when the game is active.
GameRunning(
dungeon: dungeon.Dungeon,
player: player.Player,
bullets: List(bullet.Bullet),
score: Int,
)
GameOver(fell_in_pitch: Bool)
// enemies: List(Enemy),
/// The game over screen when the player has lost.
GameOver(fell_in_pit: Bool, score: Int)
}

fn preload(p: P5) -> Assets {
let minecraftia = p5.load_font(p, "./fonts/Minecraftia-Regular.ttf")
let worksans = p5.load_font(p, "./fonts/WorkSans-Medium.ttf")

p5js_gleam.initialize_assets()
|> p5js_gleam.insert_font("minecraftia", minecraftia)
|> p5js_gleam.insert_font("worksans", worksans)
}

fn setup(p: P5) -> WorldState {
let canvas_size = dungeon.total_size()
p5.create_canvas(p, canvas_size, canvas_size)
let dungeon = dungeon.generate_dungeon()
GameRunning(
dungeon,
player.new_player(vector.Vector(canvas_size /. 2.0, canvas_size /. 2.0, 0.0)),
[],
)
StartScreen
}

fn draw(p: P5, state: WorldState) {
fn draw(p: P5, state: WorldState, assets: Assets) {
let center_text = fn(txt: String) {
let canvas_size = dungeon.total_size()
canvas_size /. 2.0 -. p5.text_width(p, txt) /. 2.0
}
let h1 = 40
let h2 = 30
let h3 = 22
let h4 = 18
let par = 14
let assert Ok(minecraftia) = p5js_gleam.get_font(assets, "minecraftia")
let assert Ok(worksans) = p5js_gleam.get_font(assets, "worksans")
let canvas_size = dungeon.total_size()

p5.background(p, "#000000")
case state {
GameRunning(dungeon, player, bullets) -> {
StartScreen -> {
let title = "BULLET HECK"
let start = "Press 'SPACE' to start"
let ctrl = "Controls"
let ctrl_move = "Use arrow keys or WASD to move"
let ctrl_jump = "Press SPACE to jump"
let ctrl_shoot = "Use mouse to aim, click to shoot"

p
|> p5.fill("#0f0f0f")
|> p5.rect(0.0, 0.0, canvas_size, canvas_size)
|> p5.text_size(h1)
|> p5.fill("#ffffff")
|> p5.text_font(minecraftia)
|> p5.text(title, center_text(title), canvas_size /. 2.0 +. 5.0)
|> p5.text_font(worksans)
|> p5.text_size(h4)
|> p5.text(start, center_text(start), canvas_size /. 2.0 +. 20.0)
// controls
|> p5.fill("#969696")
|> p5.text(ctrl, center_text(ctrl), canvas_size /. 2.0 +. 200.0)
|> p5.text_size(par)
|> p5.text(ctrl_move, center_text(ctrl_move), canvas_size /. 2.0 +. 225.0)
|> p5.text(ctrl_jump, center_text(ctrl_jump), canvas_size /. 2.0 +. 245.0)
|> p5.text(
ctrl_shoot,
center_text(ctrl_shoot),
canvas_size /. 2.0 +. 265.0,
)
}
GameRunning(dungeon, player, bullets, score) -> {
dungeon.draw(p, dungeon)
player.draw(p, player)
list.each(bullets, bullet.draw(p, _))

// Render UI
let hp_x = 22.0
let score_x = canvas_size -. 100.0

p
|> p5.no_stroke()
|> p5.fill("#660000")
|> p5.rect(0.0, 0.0, canvas_size, 36.0)
// draw health bar
|> p5.fill("#28e200")
|> p5.rect(hp_x +. 15.0, 12.0, int.to_float(player.current_health), 10.0)
|> p5.fill("#ffffff")
|> p5.text_size(par)
|> p5.text("HP:", 10.0, hp_x)
// draw score
|> p5.text("Score:", score_x, 22.0)
|> p5.text(int.to_string(score), score_x +. 45.0, 22.0)
}
GameOver(_) -> {
GameOver(fell_in_pit, score) -> {
let canvas_size = dungeon.total_size()
let game_over = "GAME OVER"
let final_score = "Final Score: "
let restart = "Press 'R' to play again"
let score_text = final_score <> int.to_string(score)
let cause_of_death = case fell_in_pit {
True -> "You fell to your death."
False -> "Turns out, red things hurt."
}

p
|> p5.fill("#0f0f0f")
|> p5.rect(0.0, 0.0, canvas_size, canvas_size)
|> p5.fill("#e20000")
|> p5.text_size(h2)
|> p5.text_font(minecraftia)
|> p5.text(game_over, center_text(game_over), canvas_size /. 2.0 -. 25.0)
|> p5.text_size(h3)
|> p5.text_font(worksans)
|> p5.text(
cause_of_death,
center_text(cause_of_death),
canvas_size /. 2.0 -. 15.0,
)
|> p5.fill("#ffffff")
|> p5.text(
score_text,
center_text(score_text),
canvas_size /. 2.0 +. 45.0,
)
|> p5.text_size(h4)
|> p5.text(restart, center_text(restart), canvas_size /. 2.0 +. 70.0)
}
}
}

fn on_key_pressed(key: String, _: Int, state: WorldState) -> WorldState {
case key, state {
" ", GameRunning(dungeon, player, bullets) ->
"r", _ -> StartScreen
" ", StartScreen -> {
let canvas_size = dungeon.total_size()
let dungeon = dungeon.generate_dungeon()
GameRunning(
dungeon,
player.new_player(vector.Vector(
canvas_size /. 2.0,
canvas_size /. 2.0,
0.0,
)),
[],
0,
)
}
" ", GameRunning(dungeon, player, bullets, score) ->
GameRunning(
dungeon: dungeon,
bullets: bullets,
player: player.jump(player),
score: score,
)
"w", GameRunning(dungeon, player, bullets) ->
"w", GameRunning(dungeon, player, bullets, score) ->
GameRunning(
dungeon: dungeon,
bullets: bullets,
player: player.accelerate_y(player, False),
score: score,
)
"s", GameRunning(dungeon, player, bullets) ->
"s", GameRunning(dungeon, player, bullets, score) ->
GameRunning(
dungeon: dungeon,
bullets: bullets,
player: player.accelerate_y(player, True),
score: score,
)
"a", GameRunning(dungeon, player, bullets) ->
"a", GameRunning(dungeon, player, bullets, score) ->
GameRunning(
dungeon: dungeon,
bullets: bullets,
player: player.accelerate_x(player, False),
score: score,
)
"d", GameRunning(dungeon, player, bullets) ->
"d", GameRunning(dungeon, player, bullets, score) ->
GameRunning(
dungeon: dungeon,
bullets: bullets,
player: player.accelerate_x(player, True),
score: score,
)
_, _ -> state
}
}

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

fn on_mouse_clicked(x: Float, y: Float, state: WorldState) -> WorldState {
case state {
GameRunning(dungeon, player, bullets) -> {
GameRunning(dungeon, player, bullets, score) -> {
use <- bool.guard(!player.can_player_fire(player), state)

let firing_direction =
Expand All @@ -137,6 +260,7 @@ fn on_mouse_clicked(x: Float, y: Float, state: WorldState) -> WorldState {
..player,
last_fire_time: utils.now_in_milliseconds(),
),
score: score,
)
}
_ -> state
Expand All @@ -145,7 +269,7 @@ fn on_mouse_clicked(x: Float, y: Float, state: WorldState) -> WorldState {

fn on_tick(state: WorldState) -> WorldState {
case state {
GameRunning(dungeon, player, bullets) -> {
GameRunning(dungeon, player, bullets, score) -> {
// Attempt to move player
let old_position = player.position
let moved = player.move(player)
Expand All @@ -166,9 +290,9 @@ fn on_tick(state: WorldState) -> WorldState {
}

use <- bool.guard(
player.position.z <. 0.0
player.position.z <=. 0.0
&& dungeon.is_over_pit(dungeon, player.position),
GameOver(True),
GameOver(True, score),
)

let player = player.update_velocity(player)
Expand Down Expand Up @@ -203,14 +327,23 @@ fn on_tick(state: WorldState) -> WorldState {
#([bullet.advance_bullet(b), ..bullets], player)
})

GameRunning(dungeon: dungeon, player: player, bullets: bullets)
GameRunning(
dungeon: dungeon,
player: player,
bullets: bullets,
score: score,
)
}
_ -> state
}
}

pub fn main() {
p5js_gleam.create_sketch(init: setup, draw: draw)
p5js_gleam.create_sketch_with_preloading(
init: setup,
draw: draw,
preload: preload,
)
|> p5js_gleam.set_on_key_pressed(on_key_pressed)
|> p5js_gleam.set_on_key_released(on_key_released)
|> p5js_gleam.set_on_mouse_clicked(on_mouse_clicked)
Expand Down

0 comments on commit b32f60c

Please sign in to comment.