Merge branch 'devel'
Fully ported from quicksilver to raylib.
This commit is contained in:
commit
e0eff5df8e
23 changed files with 4215 additions and 3100 deletions
2436
Cargo.lock
generated
2436
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
16
Cargo.toml
16
Cargo.toml
|
@ -2,11 +2,23 @@
|
|||
name = "ld45_one_and_all"
|
||||
version = "0.1.1"
|
||||
authors = ["Stephen Seo <seo.disparate@gmail.com>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
quicksilver = { version = "0.3.19", default-features = false, features = [ "fonts", "saving", "sounds" ] }
|
||||
#quicksilver = { version = "0.3.19", default-features = false, features = [ "fonts", "saving", "sounds" ] }
|
||||
rand = "0.7.2"
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.64"
|
||||
|
||||
[lib]
|
||||
name = "ld45_lib"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["rlib", "staticlib"]
|
||||
|
||||
[[bin]]
|
||||
name = "ld45_bin"
|
||||
path = "src/bin.rs"
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Stephen Seo
|
||||
Copyright (c) 2019,2023 Stephen Seo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
13
README.md
13
README.md
|
@ -1,17 +1,12 @@
|
|||
# Disclaimer
|
||||
|
||||
The hosted WASM versions of this game still work, but I am not entirely sure if
|
||||
the security issues with this game apply to the WASM versions. **USE AT YOUR OWN
|
||||
RISK**.
|
||||
|
||||
This game was created in a manner such that it was tightly coupled with the
|
||||
`quicksilver` dependency. However, `quicksilver` is no longer (actively)
|
||||
maintained, and its old dependencies no longer allow this game to run properly
|
||||
(crashes on native, cannot serve WASM version).
|
||||
This game has been ported away from quicksilver. A WASM version of the new
|
||||
version will be made soon.
|
||||
|
||||
# Entry for LD45 - Start with Nothing
|
||||
|
||||
This game is a Rust project using the quicksilver 2D game framework.
|
||||
This game is a Rust project that originally used the quicksilver 2D game
|
||||
framework. It now uses Raylib.
|
||||
|
||||
It can be run locally by invoking `cargo run` in the project directory.
|
||||
|
||||
|
|
22
build.rs
Normal file
22
build.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
extern crate bindgen;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-link-lib=raylib");
|
||||
println!("cargo:rustc-link-lib=OpenGL");
|
||||
println!("cargo:rerun-if-changed=raylib/raylib.h");
|
||||
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header("raylib/raylib.h")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
.clang_arg("-fvisibility=default")
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("raylib_bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
}
|
1568
raylib/raylib.h
Normal file
1568
raylib/raylib.h
Normal file
File diff suppressed because it is too large
Load diff
119
src/agnostic_interface.rs
Normal file
119
src/agnostic_interface.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
pub mod raylib_impl;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use crate::faux_quicksilver::{Circle, Color, Rectangle, Transform, Vector};
|
||||
|
||||
pub trait ImageInterface {
|
||||
fn draw(&mut self, x: f32, y: f32, color: Color) -> Result<(), String>;
|
||||
fn draw_sub(
|
||||
&mut self,
|
||||
sub_rect: Rectangle,
|
||||
dest_rect: Rectangle,
|
||||
color: Color,
|
||||
) -> Result<(), String>;
|
||||
fn draw_transform(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
color: Color,
|
||||
transform: Transform,
|
||||
origin: Vector,
|
||||
) -> Result<(), String>;
|
||||
fn draw_sub_transform(
|
||||
&mut self,
|
||||
sub_rect: Rectangle,
|
||||
dest_rect: Rectangle,
|
||||
color: Color,
|
||||
transform: Transform,
|
||||
origin: Vector,
|
||||
) -> Result<(), String>;
|
||||
fn get_w(&self) -> usize;
|
||||
fn get_h(&self) -> usize;
|
||||
fn get_wh_rect(&self) -> Rectangle;
|
||||
}
|
||||
|
||||
pub trait FontInterface {
|
||||
fn draw(&mut self, s: &str, size: u32, x: f32, y: f32, color: Color) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub trait SoundInterface {
|
||||
fn play(&mut self, vol: f32) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub trait MusicInterface {
|
||||
fn play(&mut self, vol: f32) -> Result<(), String>;
|
||||
fn pause(&mut self) -> Result<(), String>;
|
||||
fn stop(&mut self) -> Result<(), String>;
|
||||
fn set_loop(&mut self, loop_enable: bool) -> Result<(), String>;
|
||||
fn update(&mut self) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub trait ShaderInterface {
|
||||
fn set_transform_attrib(&mut self, transform: Transform) -> Result<(), String>;
|
||||
fn set_origin_attrib(&mut self, origin: Vector) -> Result<(), String>;
|
||||
fn set_camera_attrib(&mut self, camera: Vector) -> Result<(), String>;
|
||||
fn begin_draw_shader(&self) -> Result<(), String>;
|
||||
fn end_draw_shader(&self) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub trait CameraInterface {
|
||||
fn get_view_xy(&self) -> Result<(f32, f32), String>;
|
||||
fn set_view_xy(&mut self, x: f32, y: f32) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub trait GameInterface {
|
||||
fn get_dimensions(&self) -> Result<(f32, f32), String>;
|
||||
fn get_key_pressed(&mut self, key: char) -> Result<bool, String>;
|
||||
fn get_mouse_pressed(&mut self) -> Result<Option<(f32, f32)>, String>;
|
||||
fn get_mouse_released(&mut self) -> Result<bool, String>;
|
||||
fn get_mouse_down(&mut self) -> Result<Option<(f32, f32)>, String>;
|
||||
fn get_mouse_xy(&self) -> Result<(f32, f32), String>;
|
||||
fn get_mouse_xy_vec(&self) -> Result<Vector, String>;
|
||||
fn xy_to_world(&self, x: f32, y: f32) -> Result<Vector, String>;
|
||||
fn vec_to_world(&self, vec: Vector) -> Result<Vector, String>;
|
||||
fn get_delta_time(&self) -> f32;
|
||||
fn clear_window(&mut self, color: Color) -> Result<(), String>;
|
||||
fn begin_drawing(&mut self) -> Result<(), String>;
|
||||
fn end_drawing(&mut self) -> Result<(), String>;
|
||||
|
||||
fn draw_circle(&mut self, circle: Circle, color: Color) -> Result<(), String>;
|
||||
fn draw_circle_transform(
|
||||
&mut self,
|
||||
circle: Circle,
|
||||
color: Color,
|
||||
transform: Transform,
|
||||
origin: Vector,
|
||||
) -> Result<(), String>;
|
||||
fn draw_rect(&mut self, rect: Rectangle, color: Color) -> Result<(), String>;
|
||||
fn draw_rect_ex(
|
||||
&mut self,
|
||||
rect: Rectangle,
|
||||
color: Color,
|
||||
origin: Vector,
|
||||
rot: f32,
|
||||
) -> Result<(), String>;
|
||||
fn draw_rect_transform(
|
||||
&mut self,
|
||||
rect: Rectangle,
|
||||
color: Color,
|
||||
transform: Transform,
|
||||
origin: Vector,
|
||||
) -> Result<(), String>;
|
||||
|
||||
fn load_image(&mut self, path: &Path) -> Result<Box<dyn ImageInterface>, String>;
|
||||
fn load_font(&mut self, path: &Path) -> Result<Box<dyn FontInterface>, String>;
|
||||
fn load_sound(&mut self, path: &Path) -> Result<Box<dyn SoundInterface>, String>;
|
||||
fn load_music(&mut self, path: &Path) -> Result<Box<dyn MusicInterface>, String>;
|
||||
fn load_shader(
|
||||
&mut self,
|
||||
name: String,
|
||||
vs: &Path,
|
||||
fs: &Path,
|
||||
) -> Result<Box<dyn ShaderInterface>, String>;
|
||||
|
||||
fn get_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
|
||||
fn get_default_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
|
||||
fn set_camera(&mut self, camera: &Box<dyn CameraInterface>) -> Result<(), String>;
|
||||
fn set_camera_xy(&mut self, x: f32, y: f32) -> Result<(), String>;
|
||||
}
|
1075
src/agnostic_interface/raylib_impl.rs
Normal file
1075
src/agnostic_interface/raylib_impl.rs
Normal file
File diff suppressed because it is too large
Load diff
17
src/bin.rs
Normal file
17
src/bin.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use ld45_lib::agnostic_interface;
|
||||
|
||||
fn will_close() -> bool {
|
||||
unsafe { agnostic_interface::raylib_impl::ffi::WindowShouldClose() }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let state_ptr = ld45_lib::ld45_initialize();
|
||||
|
||||
while !will_close() {
|
||||
ld45_lib::ld45_iterate(state_ptr);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
drop(Box::from_raw(state_ptr as *mut ld45_lib::WasmState));
|
||||
}
|
||||
}
|
352
src/faux_quicksilver.rs
Normal file
352
src/faux_quicksilver.rs
Normal file
|
@ -0,0 +1,352 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
|
||||
use std::path::Path;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::agnostic_interface::{
|
||||
FontInterface, GameInterface, ImageInterface, MusicInterface, SoundInterface,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Color {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const WHITE: Self = Self {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
pub const BLACK: Self = Self {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
pub const GREEN: Self = Self {
|
||||
r: 0,
|
||||
g: 255,
|
||||
b: 0,
|
||||
a: 255,
|
||||
};
|
||||
|
||||
pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Rectangle {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub w: f32,
|
||||
pub h: f32,
|
||||
}
|
||||
|
||||
impl Rectangle {
|
||||
pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self {
|
||||
Self { x, y, w, h }
|
||||
}
|
||||
|
||||
pub fn pos_add_vec(&mut self, v: Vector) {
|
||||
self.x += v.x;
|
||||
self.y += v.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Rectangle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
w: 1.0,
|
||||
h: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Circle {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub r: f32,
|
||||
}
|
||||
|
||||
impl Circle {
|
||||
pub fn new(x: f32, y: f32, r: f32) -> Self {
|
||||
Self { x, y, r }
|
||||
}
|
||||
|
||||
pub fn pos_add_vec(&mut self, v: Vector) {
|
||||
self.x += v.x;
|
||||
self.y += v.y;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Vector {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Add<Vector> for Vector {
|
||||
type Output = Vector;
|
||||
|
||||
fn add(self, rhs: Vector) -> Self::Output {
|
||||
Vector {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Vector> for Vector {
|
||||
type Output = Vector;
|
||||
|
||||
fn sub(self, rhs: Vector) -> Self::Output {
|
||||
Vector {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Vector> for Vector {
|
||||
fn add_assign(&mut self, rhs: Vector) {
|
||||
self.x += rhs.x;
|
||||
self.y += rhs.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<Vector> for Vector {
|
||||
fn sub_assign(&mut self, rhs: Vector) {
|
||||
self.x -= rhs.x;
|
||||
self.y -= rhs.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vector {
|
||||
type Output = Vector;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Vector {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Vector {
|
||||
pub fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Vector {
|
||||
fn from(t: (f32, f32)) -> Self {
|
||||
Self { x: t.0, y: t.1 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Transform {
|
||||
pub mat: [f32; 9],
|
||||
}
|
||||
|
||||
impl Default for Transform {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vector> for Transform {
|
||||
type Output = Vector;
|
||||
|
||||
fn mul(self, rhs: Vector) -> Self::Output {
|
||||
Vector {
|
||||
x: rhs.x * self.mat[0] + rhs.y * self.mat[1] + self.mat[2],
|
||||
y: rhs.x * self.mat[3] + rhs.y * self.mat[4] + self.mat[5],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Transform> for Transform {
|
||||
type Output = Transform;
|
||||
|
||||
fn mul(self, rhs: Transform) -> Self::Output {
|
||||
Self {
|
||||
mat: [
|
||||
self.mat[0] * rhs.mat[0] + self.mat[1] * rhs.mat[3] + self.mat[2] * rhs.mat[6],
|
||||
self.mat[0] * rhs.mat[1] + self.mat[1] * rhs.mat[4] + self.mat[2] * rhs.mat[7],
|
||||
self.mat[0] * rhs.mat[2] + self.mat[1] * rhs.mat[5] + self.mat[2] * rhs.mat[8],
|
||||
self.mat[3] * rhs.mat[0] + self.mat[4] * rhs.mat[3] + self.mat[5] * rhs.mat[6],
|
||||
self.mat[3] * rhs.mat[1] + self.mat[4] * rhs.mat[4] + self.mat[5] * rhs.mat[7],
|
||||
self.mat[3] * rhs.mat[2] + self.mat[4] * rhs.mat[5] + self.mat[5] * rhs.mat[8],
|
||||
self.mat[6] * rhs.mat[0] + self.mat[7] * rhs.mat[3] + self.mat[8] * rhs.mat[6],
|
||||
self.mat[6] * rhs.mat[1] + self.mat[7] * rhs.mat[4] + self.mat[8] * rhs.mat[7],
|
||||
self.mat[6] * rhs.mat[2] + self.mat[7] * rhs.mat[5] + self.mat[8] * rhs.mat[8],
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
pub const IDENTITY: Self = Self {
|
||||
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
|
||||
};
|
||||
|
||||
pub fn rotate(rot: f32) -> Self {
|
||||
Self {
|
||||
mat: [
|
||||
rot.cos(),
|
||||
-rot.sin(),
|
||||
0.0,
|
||||
rot.sin(),
|
||||
rot.cos(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn translate(x: f32, y: f32) -> Self {
|
||||
Self {
|
||||
mat: [1.0, 0.0, x, 0.0, 1.0, y, 0.0, 0.0, 1.0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
gi: Box<dyn GameInterface>,
|
||||
images: HashMap<String, Box<dyn ImageInterface>>,
|
||||
fonts: HashMap<String, Box<dyn FontInterface>>,
|
||||
sounds: HashMap<String, Box<dyn SoundInterface>>,
|
||||
music: HashMap<String, Box<dyn MusicInterface>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(gi: Box<dyn GameInterface>) -> Self {
|
||||
Self {
|
||||
gi,
|
||||
images: HashMap::new(),
|
||||
fonts: HashMap::new(),
|
||||
sounds: HashMap::new(),
|
||||
music: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_gi(&self) -> &dyn GameInterface {
|
||||
self.gi.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_gi_mut(&mut self) -> &mut dyn GameInterface {
|
||||
self.gi.as_mut()
|
||||
}
|
||||
|
||||
pub fn load_image(&mut self, path: &Path, name: String) -> Result<(), String> {
|
||||
self.images.insert(name, self.gi.load_image(path)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_font(&mut self, path: &Path, name: String) -> Result<(), String> {
|
||||
self.fonts.insert(name, self.gi.load_font(path)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_sound(&mut self, path: &Path, name: String) -> Result<(), String> {
|
||||
self.sounds.insert(name, self.gi.load_sound(path)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_music(&mut self, path: &Path, name: String) -> Result<(), String> {
|
||||
self.music.insert(name, self.gi.load_music(path)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_image(&self, name: &str) -> Result<&dyn ImageInterface, String> {
|
||||
Ok(self
|
||||
.images
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Image \"{name}\" not found"))?
|
||||
.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_image_mut(&mut self, name: &str) -> Result<&mut dyn ImageInterface, String> {
|
||||
Ok(self
|
||||
.images
|
||||
.get_mut(name)
|
||||
.ok_or_else(|| format!("Image \"{name}\" not found"))?
|
||||
.as_mut())
|
||||
}
|
||||
|
||||
pub fn get_font(&self, name: &str) -> Result<&dyn FontInterface, String> {
|
||||
Ok(self
|
||||
.fonts
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Font \"{name}\" not found"))?
|
||||
.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_font_mut(&mut self, name: &str) -> Result<&mut dyn FontInterface, String> {
|
||||
Ok(self
|
||||
.fonts
|
||||
.get_mut(name)
|
||||
.ok_or_else(|| format!("Font \"{name}\" not found"))?
|
||||
.as_mut())
|
||||
}
|
||||
|
||||
pub fn get_sound(&self, name: &str) -> Result<&dyn SoundInterface, String> {
|
||||
Ok(self
|
||||
.sounds
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Sound \"{name}\" not found"))?
|
||||
.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_sound_mut(&mut self, name: &str) -> Result<&mut dyn SoundInterface, String> {
|
||||
Ok(self
|
||||
.sounds
|
||||
.get_mut(name)
|
||||
.ok_or_else(|| format!("Sound \"{name}\" not found"))?
|
||||
.as_mut())
|
||||
}
|
||||
|
||||
pub fn get_music(&self, name: &str) -> Result<&dyn MusicInterface, String> {
|
||||
Ok(self
|
||||
.music
|
||||
.get(name)
|
||||
.ok_or_else(|| format!("Music \"{name}\" not found"))?
|
||||
.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_music_mut(&mut self, name: &str) -> Result<&mut dyn MusicInterface, String> {
|
||||
Ok(self
|
||||
.music
|
||||
.get_mut(name)
|
||||
.ok_or_else(|| format!("Music \"{name}\" not found"))?
|
||||
.as_mut())
|
||||
}
|
||||
|
||||
pub fn update_music(&mut self) -> Result<(), String> {
|
||||
for (_, music) in &mut self.music {
|
||||
music.update()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
48
src/lib.rs
Normal file
48
src/lib.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
pub mod agnostic_interface;
|
||||
mod faux_quicksilver;
|
||||
mod original_impl;
|
||||
mod shaders;
|
||||
|
||||
use agnostic_interface::raylib_impl::RaylibGame;
|
||||
use faux_quicksilver::Window;
|
||||
use original_impl::GameState;
|
||||
|
||||
pub struct WasmState {
|
||||
pub window: Window,
|
||||
pub game_state: GameState,
|
||||
}
|
||||
|
||||
impl WasmState {
|
||||
pub fn get_window_mut(&mut self) -> &mut Window {
|
||||
&mut self.window
|
||||
}
|
||||
|
||||
pub fn get_state_mut(&mut self) -> &mut GameState {
|
||||
&mut self.game_state
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ld45_initialize() -> *mut ::std::os::raw::c_void {
|
||||
let game_interface = RaylibGame::new_boxed(800, 600);
|
||||
let mut window = Window::new(game_interface);
|
||||
let game_state = GameState::new(&mut window).unwrap();
|
||||
|
||||
Box::into_raw(Box::new(WasmState { window, game_state })) as *mut ::std::os::raw::c_void
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ld45_iterate(context: *mut ::std::os::raw::c_void) {
|
||||
let state_ptr = context as *mut WasmState;
|
||||
unsafe {
|
||||
(*state_ptr).get_window_mut().update_music().unwrap();
|
||||
(*state_ptr)
|
||||
.get_state_mut()
|
||||
.update(&mut (*state_ptr).get_window_mut())
|
||||
.unwrap();
|
||||
(*state_ptr)
|
||||
.get_state_mut()
|
||||
.draw(&mut (*state_ptr).get_window_mut())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
47
src/shaders.rs
Normal file
47
src/shaders.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use crate::{
|
||||
agnostic_interface::raylib_impl::RaylibShader,
|
||||
faux_quicksilver::{Transform, Vector},
|
||||
};
|
||||
use std::ffi::CStr;
|
||||
|
||||
extern "C" {
|
||||
pub fn glVertexAttrib2f(index: ::std::os::raw::c_uint, x: f32, y: f32);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn glVertexAttrib3f(index: ::std::os::raw::c_uint, x: f32, y: f32, z: f32);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn glVertexAttrib4f(index: ::std::os::raw::c_uint, x: f32, y: f32, z: f32, w: f32);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn glGetAttribLocation(
|
||||
program: ::std::os::raw::c_uint,
|
||||
name: *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
pub fn get_attrib_location(raylib_shader: &RaylibShader, name: &CStr) -> ::std::os::raw::c_uint {
|
||||
unsafe {
|
||||
glGetAttribLocation(raylib_shader.get_shader_id(), name.as_ptr()) as ::std::os::raw::c_uint
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_transform_3f(index: ::std::os::raw::c_uint, transform: Transform) {
|
||||
// OpenGL stores matrix indices in column major order.
|
||||
for (i, idx) in (index..(index + 3)).enumerate() {
|
||||
unsafe {
|
||||
glVertexAttrib3f(
|
||||
idx,
|
||||
transform.mat[0 + i as usize],
|
||||
transform.mat[3 + i as usize],
|
||||
transform.mat[6 + i as usize],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_attr_2f(index: ::std::os::raw::c_uint, origin: Vector) {
|
||||
unsafe {
|
||||
glVertexAttrib2f(index, origin.x, origin.y);
|
||||
}
|
||||
}
|
23
static/camera.vs
Normal file
23
static/camera.vs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#version 100
|
||||
|
||||
// Input vertex attributes
|
||||
attribute vec3 vertexPosition;
|
||||
attribute vec2 vertexTexCoord;
|
||||
attribute vec4 vertexColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform mat4 mvp;
|
||||
|
||||
// Output vertex attributes (to fragment shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// custom
|
||||
attribute vec2 camera;
|
||||
|
||||
void main() {
|
||||
fragTexCoord = vertexTexCoord;
|
||||
fragColor = vertexColor;
|
||||
|
||||
gl_Position = mvp * vec4(vertexPosition - vec3(camera, 0.0), 1.0);
|
||||
}
|
20
static/simple.fs
Normal file
20
static/simple.fs
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 100
|
||||
|
||||
// Default fragment shader used by Raylib.
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
void main() {
|
||||
// Texel color fetching from texture sampler
|
||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||
|
||||
gl_FragColor = texelColor*colDiffuse*fragColor;
|
||||
}
|
26
static/transform.vs
Normal file
26
static/transform.vs
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 100
|
||||
|
||||
// Input vertex attributes
|
||||
attribute vec3 vertexPosition;
|
||||
attribute vec2 vertexTexCoord;
|
||||
attribute vec4 vertexColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform mat4 mvp;
|
||||
|
||||
// Output vertex attributes (to fragment shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// custom
|
||||
attribute vec2 camera;
|
||||
attribute vec2 origin;
|
||||
attribute mat3 transform;
|
||||
|
||||
void main() {
|
||||
fragTexCoord = vertexTexCoord;
|
||||
fragColor = vertexColor;
|
||||
|
||||
vec3 pos = transform * (vertexPosition - vec3(origin, 0.0)) + vec3(origin, 0.0);
|
||||
gl_Position = mvp * vec4(pos - vec3(camera, 0.0), 1.0);
|
||||
}
|
5
wasm/.gitignore
vendored
Normal file
5
wasm/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/ld45.html
|
||||
/ld45.js
|
||||
/ld45.data
|
||||
/ld45.wasm
|
||||
/index.html
|
32
wasm/Makefile
Normal file
32
wasm/Makefile
Normal file
|
@ -0,0 +1,32 @@
|
|||
CC = source "${HOME}/git/emsdk/emsdk_env.sh" && emcc
|
||||
|
||||
all: ld45.html
|
||||
|
||||
ld45.html: src/main.c ../target/wasm32-unknown-emscripten/release/libld45_lib.a
|
||||
${CC} -o ld45.html -s USE_GLFW=3 -Iinclude \
|
||||
-Llib -lraylib \
|
||||
-L../target/wasm32-unknown-emscripten/release -lld45_lib \
|
||||
-sTOTAL_MEMORY=1024MB \
|
||||
-sALLOW_MEMORY_GROWTH=1 \
|
||||
-O2 \
|
||||
-fsanitize=address \
|
||||
-sEXPORTED_FUNCTIONS="['_malloc', '_main']" \
|
||||
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap \
|
||||
--preload-file ../static src/main.c
|
||||
ln -sf ld45.html index.html
|
||||
|
||||
#-fsanitize=address \
|
||||
#-sWARN_UNALIGNED=1 \
|
||||
|
||||
../target/wasm32-unknown-emscripten/release/libld45_lib.a: ../src/lib.rs
|
||||
cd ..; source "${HOME}/git/emsdk/emsdk_env.sh"; cargo build --lib --release --target wasm32-unknown-emscripten
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f ld45.html
|
||||
rm -f ld45.js
|
||||
rm -f ld45.wasm
|
||||
rm -f ld45.data
|
||||
rm -f index.html
|
||||
cd ..; cargo clean
|
1
wasm/emsdk_version
Normal file
1
wasm/emsdk_version
Normal file
|
@ -0,0 +1 @@
|
|||
3.1.32
|
8
wasm/include/ld45_lib.h
Normal file
8
wasm/include/ld45_lib.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef LD45_ONE_AND_ALL_LIB_H_
|
||||
#define LD45_ONE_AND_ALL_LIB_H_
|
||||
|
||||
extern void *ld45_initialize();
|
||||
|
||||
extern void ld45_iterate(void *context);
|
||||
|
||||
#endif
|
1
wasm/include/raylib.h
Symbolic link
1
wasm/include/raylib.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../raylib/raylib.h
|
BIN
wasm/lib/libraylib.a
Normal file
BIN
wasm/lib/libraylib.a
Normal file
Binary file not shown.
18
wasm/src/main.c
Normal file
18
wasm/src/main.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include <ld45_lib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void main_loop(void *ud) {
|
||||
ld45_iterate(ud);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
void *ld45_context = ld45_initialize();
|
||||
|
||||
emscripten_set_main_loop_arg(main_loop, ld45_context, 0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue