Merge branch 'devel'
Fully ported from quicksilver to raylib.
This commit is contained in:
commit
e0eff5df8e
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