Client is approx 5% done

This commit is contained in:
2026-05-20 21:51:09 +01:00
parent 556185e095
commit 29565949b0
9 changed files with 2229 additions and 4 deletions
+2059
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "happening-client"
version = "0.1.0"
edition = "2024"
[dependencies]
macroquad = "0.4.15"
phf = {version="0.13.1",features=["macros"]}
reqwest = {version="0.13.3",features=["blocking","json"]}
serde = {version="1.0.228",features=["derive"]}
serde_json = "1.0.149"
-64
View File
@@ -1,64 +0,0 @@
import requests
import os
import time
import sys
debug = False
try:
if sys.argv[1] == "debug": debug = True
except:
debug = False
# Loop and get new api
def main():
response = {}
id = -1
while True:
try:
response = api_get()
if debug: print(response)
match response["action_type"]:
case "output":
character = get_character(response["character"])
output(character, response["content"])
case "choice":
user_choice = choice(response["choices"])
time.sleep(0.5)
continue
case "end":
print("Exitting successfully")
os._exit(0)
except:
print("Server not up or cannot be reached")
input() # Enter to go to next loop (testing)
# Make choice
def choice(choices):
api_url = "http://localhost:20264/choice"
for (index,choice) in enumerate(choices):
print(f"{index}: {choice}")
try:
choice = int(input())
except:
choice = 0
print("Invalid choice, defaulting to 0")
requests.post(api_url, json=choice);
# Character outputs text to the user
def output(character, text):
print(character["name"], "says")
print(text)
# Get user from the backend
def get_character(character):
if character.lower() == "narrator":
return {"name": "narrator"}
api_url = f"http://localhost:20264/character/{character}"
return requests.get(api_url).json()
# Normal API request
def api_get():
api_url = "http://localhost:20264/happening/"
response = requests.get(api_url).json()
return response
main()
+155
View File
@@ -0,0 +1,155 @@
use macroquad::prelude::*;
use reqwest::*;
use reqwest::blocking;
use std::collections::HashMap;
use phf::phf_map;
use std::{thread, time::Duration};
use serde::
{
Serialize,
Deserialize,
};
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct Data {
pub action_type: String,
pub content: String,
pub character: String,
pub choices: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
#[serde(default)]
pub struct Character
{
name: String,
gender: String,
eye_color: Colour,
hair_color: Colour,
skin_color: Colour,
pronoun_subject: String,
pronoun_object: String,
pronoun_deppos: String,
pronoun_indpos: String,
pronoun_reflex: String,
head_shape: String,
hair_style: String,
torso_shape: String,
arm_shape: String,
leg_shape: String,
clothing: Clothing,
}
#[derive(Debug,Deserialize,Serialize,Clone,Default)]
#[serde(default)]
pub struct Clothing
{
top: String,
bottom: String,
shoes: String,
}
#[derive(Debug,Deserialize,Serialize,Clone,Default)]
#[serde(default)]
pub struct Colour
{
red: u8,
green: u8,
blue: u8,
}
static POSITIONS: phf::Map<&'static str, [f32;2]> = phf_map! [
"fl" => [0.0,500.0],
"bl" => [0.0,0.0],
"fr" => [500.0,500.0],
"br" => [500.0,0.0],
];
#[macroquad::main("happening")]
async fn main()
{
let mut characters: HashMap<String, (Character, Texture2D)> = HashMap::new();
let mut textures: Vec<(Texture2D, f32, f32, Color)> = Vec::new();
loop
{
clear_background(RED);
// Get the next character
let data = next_happening();
let character_name: &str = data.character.as_str();
// Add the character to the HashMap if it's not already
if character_name != "" && !characters.contains_key(character_name)
{
let new_character = get_character(character_name).await;
characters.insert(character_name.to_string(), new_character);
}
// Matchbox for all the commands
match data.action_type.to_lowercase().as_str()
{
"output" =>
{
println!("SAYING");
draw_text(characters[character_name].0.name.clone(), 50.0,20.0,40.0,WHITE);
draw_text(data.content.as_str(), 50.0,40.0,30.0,WHITE);
},
"to" =>
{
let position = POSITIONS.get(&data.content).cloned().unwrap();
let texture = &characters[character_name].1;
textures.push((texture.clone(), position[0], position[1], WHITE)); // Heavy
}
_ => println!("Unknown action"),
}
for (texture, x, y, colour) in &textures
{
draw_texture(&texture, *x, *y, *colour);
}
thread::sleep(Duration::from_millis(1000));
next_frame().await;
}
}
fn next_happening()
-> Data
{
let data: Data = reqwest::blocking::get(format!("http://127.0.0.1:20264/happening")).unwrap().json().unwrap();
println!("{data:?}");
data
}
async fn get_character(name: &str)
-> (Character, Texture2D)
{
let character: Character = reqwest::blocking::get(format!("http://127.0.0.1:20264/character/{name}")).unwrap().json().unwrap();
println!("{character:?}");
let skin_colour = character.skin_color.clone();
let skin: Color = Color::from_rgba(skin_colour.red,skin_colour.green,skin_colour.blue,255);
let hair_colour = character.hair_color.clone();
let hair: Color = Color::from_rgba(hair_colour.red,hair_colour.green,hair_colour.blue,255);
let head_path: String = format!("../images/head/{}.png",character.head_shape);
let head: Texture2D = change_colour(&mut load_image(head_path.as_str()).await.unwrap(), &skin, &hair);
(character, head)
}
fn change_colour(image: &mut Image, skin: &Color, hair: &Color)
-> Texture2D
{
let target = Color::from_rgba(255,0,255,255);
for y in 0..image.height() {
for x in 0..image.width() {
let pixel = image.get_pixel(x as u32, y as u32);
if pixel == target {
image.set_pixel(x as u32, y as u32, *skin);
}
}
}
let target = Color::from_rgba(0,255,255,255);
for y in 0..image.height() {
for x in 0..image.width() {
let pixel = image.get_pixel(x as u32, y as u32);
if pixel == target {
image.set_pixel(x as u32, y as u32, *hair);
}
}
}
Texture2D::from_image(&image)
}