You are browsing as a guest. Sign up (or log in) to start making projects!

immaturegoat

@immaturegoat

Joined June 13th, 2026

  • 31Devlogs
  • 11Projects
  • 5Ships
  • 64Votes
It is the very ridiculous juvenility that gives color to life.
https://github.com/immaturegoat
Open comments for this post

28m 58s logged

Devlog 2

I built a simple notes app that just stores what you type in a text app into local storage. I’m going to finish the project with a few other apps first.

0
0
7
Open comments for this post

1h 24m 50s logged

Devlog 1

I lowkey just needed 50 more stardust, so I’m doing this project.

Anyway, I’m just following the guide and customizing it to my liking. I’ve added a welcome screen, but I’ll add more later. I’ve also styled the close buttons and the dragging mechanic.

0
0
12
Ship

This is a new tab page that I have created. It has all the features that I think are necessary for a new tab page, and then some features for me to make my life more convenient.

Firstly, it has the date and time placed very obviously in the center. This is a way for me to easily figure out what date it is, because sometimes I forgot. The search bar is placed right under it.

Underneath the search bar, there are 4 links for what I use a lot. The 4 shortcuts go to Reddit, Discord, GitHub, and YouTube, though later in the future I might add the option to change or add more.

In the bottom, there are 3 widgets. One is a list of upcoming Codeforces Competitions (I do a lot of competetive programming), a calendar (so I can plan things better), and a to-do list (to keep me organized).

Try project → See source code →
Open comments for this post

44m 1s logged

Devlog 2

I spent around 30 minutes working on gathering contest info from codeforces and making a todo list.

the shortcuts were pretty easy to implement, because they’re just links after all. the calendar was a bit hard to implement but I think it turned out looking pretty good. The todo list was also pretty easy, because it’s just a matter of storing stuff in local storage. As for the codeforces contests, I just grabbed contest information and took the date information and reformatted it into a date and time.

0
0
19
Open comments for this post

29m 23s logged

Devlog 1

I just need the stardust bro

Anyway, I started making the basic time and date work. I think it looks pretty good! I’m going to add some other stuff later.

0
0
18
Open comments for this post

56m 14s logged

Devlog 1

I’m making a website that lets you quickly look at codeforces stats, cuz I’ve recently rebegun my codeforces grinding.

I’m coding this in Rust because I want to practice using it, and so I’ve been working on gathering the information from the Rust API. Right now, I’m using some structs to store the data.

0
0
19
Open comments for this post

57m 14s logged

To make this website look less bland, I’ve added some cards of some of the things I like in the background. The top row goes from right to left and the bottom row goes from left to right. It became a little distracting, so I decided to add a small half transparent black rectangle on top of them to dim it. I’ve also set overflow to hidden so there’s no scroll. I might add projects later, but I always thought that was unnecessary.

Oh wait, I also changed my profile picture on a lot of platforms, so I had to update the one on my website.

0
0
10
Open comments for this post

1h 7m 58s logged

I started remodeling my personal site. I think this time, I’m focusing more on a minimalistic theme (because I’m bad at designing so this gives me a way to avoid having to do web design heh AND it is also super easy to make it repsonsive) and I think it’s turning out pretty good so far. I don’t want it to just be this bland though, so I’m gonna add some stuff in the background.

0
0
21
Ship

IMPORTANT: documentation: https://github.com/immaturegoat/matu/blob/main/docs.md
tutorial: https://github.com/immaturegoat/matu/blob/main/tutorial.md

This is matu, a web game engine, designed to build and export 2D games. It features a node system with groups, objects, sprites, labels, audio, and scripts, asset uploading, viewport testing, saving and loading, and exporting into a web playable. It was inspired by editors like Unity and Godot, but I wanted to keep some simplicity similar to that of Scratch. It’s not that powerful, but it should be enough to make some simple games. The tutorial and documentation is linked above.

  • 11 devlogs
  • 33h
  • 16.37x multiplier
  • 534 Stardust
Try project → See source code →
Open comments for this post

6h 12m 38s logged

Devlog 10

Can’t believe my last devlog was two weeks ago…

Anyway, here’s what I’ve been working on.

Exporting and saving

It works! Probably… I’m pretty sure it works. At least for my testing. If you guys find any bugs, be sure to tell me.

a BUNCH of bug fixes

  • Stop highlighting nodes when reordering
  • Change matuapi rotation funcs from radians to degrees
  • Clicking off node unselects it
  • Favicon
  • After game ends, if clones are still there, stop them from showing up
  • Checkboxes on export menu
  • Remove eval classUpdate documentation

Sorry that this devlog is pretty short, for a 5 hour devlog. I’m just kinda tired of writing tbh and I can’t wait to ship this.

0
0
25
Open comments for this post

1h 47m 7s logged

probably gonna be the only devlog

I made bad apple run in terminal using the cascii rust crate to convert the video to frames, and then drew those frames while clearing the terminal. This is just a joke project so I’m not gonna ship it or anything.


Here’s the code, but it’s pretty bad. I’m by no means the greatest programmer. There’s also a lot of warnings, but I’m too lazy to fix them.

use cascii::{AsciiConverter, VideoOptions, ConversionOptions};
use std::path: :Path;
use std::fs::{self, File};
use std::io::Read;
use terminal_size::{Width, Height, terminal_size};
use crossterm::{
    cursor::{Hide, Show, MoveTo},
    execute,
    terminal::{Clear, ClearType},
};
use std::io::{self, stdout};
use std::thread;
use std::time::Duration;

fn main() -> std::io::Result<()> {    

    if !Path::new("output_frames").is_dir() {
        get_frames();
    }
    let mut frames: Vec<String> = read_files()?;

    play_animation(frames)?;
    // println!("{}", frames[0]);
    Ok(())
}

fn get_frames() -> Result<(), Box<dyn std::error: :Error>> {
    let converter = AsciiConverter::new();
    
    let size = terminal_size();
    let mut width: u32 = 80;
    let mut height = 0;
    if let Some((Width(w), Height(h))) = size {
        width = u32::from(w);
    } else {
        println!("unable to get terminal size");
    }

    let video_options = VideoOptions {
        fps: 30,
        start: Some("0".to_string()),
        end: Some("10".to_string()),
        columns: width,
        extract_audio: false,
        preprocess_filter: None,
    };

    let conversion_options = ConversionOptions::default().with_font_ratio(0.2).with_luminance(20).with_columns(width);

    converter.convert_video(Path::new("assets/apple.mp4"), Path::new("output_frames"), &video_options, &conversion_options, false)?;

    Ok(())
}

fn read_files() -> std::io::Result<Vec<String>> {
    let mut files  = Vec::new();

    for file in fs::read_dir("output_frames/").unwrap() {
        files.push(file.unwrap().path().display().to_string());
    }

    files.sort();

    let mut frames: Vec<String> = Vec::new();
    for file in files {
        let content = fs::read_to_string(file);
        let frame = match content {
            Ok(val) => val,
            Err(err) => format!("error: {}", err),
        };

        frames.push(frame);
    }
    Ok(frames)
}

fn play_animation(frames: Vec<String>) -> io::Result<()> {
    let frame = 0;
    let mut stdout = stdout();
    
    for frame in &frames {
        execute!(stdout, Hide, Clear(ClearType::All))?;    
        execute!(stdout, MoveTo(0, 0));
        println!("{}", frame);
        thread::sleep(Duration::from_millis(33));
    }

    execute!(stdout, Show)?;
    Ok(())
}
0
0
11
Open comments for this post

1h 29m 1s logged

Devlog 9

Probably my last devlog before working on saving and exporting T-T


What I worked on

Stops in scripting

I can’t believe I didn’t add this earlier, but you can now end the game using matu.runtime.stop();

Label nodes

You can now have text labels in your game! I also added scripting implementation, so you can change what the text says during a run.

Fixed reordering

Reordering nodes was a bit clunky, so I fixed it (turns out there were some bugs in the CSS and the dragging), but now it should be smoother!

1
0
18
Open comments for this post

1h 54m 30s logged

Devlog 8

This is probably gonna be a shorter devlog, but basically I made scripting a lot easier in my game engine!


Each script node now has a button in the top right of the inspector editor. I just reused the asset previews but with a textarea. This means you can have multiple popouts open at a time while scripting. It also gives you a much wider area to code in, as the inspector is kinda cramped. All updates in the popout update with the inspector textarea. The popouts are also resizable!


QoL improvements

Tab for indent

Before, if you typed tab while scripting, it would just move focus to another button instead of indenting. However, now when you press tab, 4 spaces are added. You can select multiple lines to indent multiple lines, and press shift + tab to unindent lines.

Auto-close pairs

Now when you type a character like ( or [ automatically types its closing pair and places your cursor in between them. If you type the closing pair again, it will move your cursor to the outside. As well as that, deleting an empty pair will delete both characters.

Auto-indent on enter

Now when you go to another line, it will inherit the indentation of the line above it. :)


What’s next?

I really thought that with the introduction of scripting popouts, I would be getting close to finishing the project, but over the past few days, I’ve realized that there are still a lot of stuff I want to implement. First, I want to add a Label node, allowing users to display text easily. Next (and I can’t believe I haven’t implemented this yet), I want to add a way for the user to stop the game in the script, instead of clicking the stop button. I want to fix node reordering, as right now it is a bit clunky, and of course, the final thing for me to do is to add exporting, saving, and loading.

0
0
18
Open comments for this post

3h 7m 27s logged

Devlog 7

It’s been some time since I have posted a devlog on this project. I got a little sidetracked and spent a few days working with Rust. It’s probably gonna be my next project (flashcard app, I know, how original), but I’ve also spent some time working on scripting!


So scripting was actually easier than I thought to implement. I have a const in my runtime.js file called matuAPI and it has every special function as well as what to do when that function is called. I’ll attach a screenshot of a section below. So now, on to what I have added!


  • node lookup
  • cloning
  • spawning
  • input
  • rotation
  • movement
  • dimensions (width + height) changes
  • opacity changes
  • visibility
  • asset changes
  • playing and sotpping audio
  • collision
  • global variables
  • changing bg color
  • and timers!

Wow, that was a lot! Unfortunately, as I was writing this devlog, I realized that I forgot to add a function that lets you change which sprite is being displayed in an object as well as changing the audio source asset. How does this always happen to me? Ok, I’ll be back in a bit. I need to add that real quick.


Ok, I have returned! I have added them to the code and the documentation (which is just a markdown file), so we also have

  • changing sprites
  • and changing audio assets!

Thanks for reading this devlog! Up next, I plan to add a pop out window for scripting (as the current one is too small) and of course, exporting, loading, and saving (I’m scared, save me)

0
0
5
Open comments for this post

2h 46m 1s logged

Devlog 6

This is probably going to be my last devlog before I work on scripting. I’ve put it off for too long, and right now, scripting is pretty limited (it has a start, end, input detection, movement, and console log function). I plan to add a LOT more to scripting, like changing sprites, changing opacity, rotation, cloning, deleting, audio, preview, and more. I also plan to open up the script in a window similar to the preview windows, because coding in the inspector sidebar is a bit constricting. Now, on to what I have been working on!


Audio preview

I can’t believe I put this off for so long, but it finally works. You can play audio from the preview window. Though, it’s a bit ugly right now so I plan on changing that later.

Value tags for opacity and volume

Before this, the two sliders were just sliders, and you couldn’t bring it to a specific value. However, there are now inputs on the right side of the sliders, allowing you to see what number the slider is at and allowing you to input your own values.

Unique names for nodes

I actually created two systems for this. So my idea for the node naming system is that unique names are kept separate across node types. That means that I can have an object called Thing and a group called Thing. My first idea of implementing this was to create a Set() for each node type. So I created group_names = new Set(), object_names = new Set(), sprite_names = new Set(), and so forth for each node type. Then we reuse the renaming function from script.js for the assets, but change it to have a switch statement based on the type. However, this was kind of hard, implementing a switch statement everywhere a rename or deletion or any sort of change happened. I replaced it by simpling using the hierarchy_nodes Map, which contains the names and types of each node. With this, we can just pull the type from the map to make sure that names are kept separate across types. It removes the big switch statements that were everywhere and overall keeps the code much cleaner.

Rearranging nodes

Previously, you could technically reorder things because I previously added reparenting, allowing you to move nodes from one parent to another, but it doesn’t allow you to rearrange nodes within a parent. Now, you can, and although its a bit clunky, it does work and I think it looks good.


Alright, thanks for coming to this TED talk. The next devlog will be about a lot of changes that I will make to scripting.

0
0
11
Open comments for this post

3h 11m 56s logged

Devlog 5

I was too lazy to add all the features other than basic functionality to scripting, so I decided to work on some small bugs and features instead.

Also, today I learned that you can ATTACH MULTIPLE SCREENSHOTS. This is like a gamechanger lol I can’t believe I didn’t know this.


Extra line at the end of the viewport grid

For the grid in the center of the screen, the function I used to draw it didn’t close it off on the right side. I can’t believe it took until now to fix it :|

Changed hierarchy node symbols

I changed the symbols on the left side of each of the nodes from emojis to letters. I used emojis because I didn’t want to find assets (sorry), but recently I’ve been feeling like the emojis make it feel AI-generated, so I removed those. Also, a bonus of changing them to letters is having the ability to now have the same name be used across different node types, but when you call them in code, you have to do like G:Object or O:Object.

Fixed opacity slider position

You might’ve seen in my last devlog, something kind of crazy happened with the slider… Anyway, it’s fixed now, so that’s good! I also ended up customizing the slider.

Width and height lock

Before this, I didn’t have a way for users to lock dimensions. I’ve implemented two checkboxes into the inspector, dimension lock and proportion lock. Dimension lock takes the current dimensions and keeps that ratio, while proportion lock keeps the original dimension ratio of the original asset.

Closing the correct inspector

Basically, there used to be a bug where if you deleted one asset while another asset was open in the inspector, it would close the inspector. It wasn’t harmful or anything, but it was really annoying. This was a pretty simple fix. I just added a check where the name of the asset in the inspector is compared to the name of the asset being deleted.

Changing console color

I don’t know if I mentioned this in a previous devlog yet, but I added a console for errors from scripting to show! It also displays start and end times. However, it was the wrong color for so long and I didn’t notice. It was just because I put the wrong class name in the css…

Refreshing asset options

This was also a bug that was really annoying. When you created a sprite and opened it up in the inspector, when you uploaded a new asset, it wouldn’t show up in the inspector. This was also pretty easy to fix. I just created a helper function, which basically just remakes the asset select options, and then called it every time an asset is changed, like when one is renamed, uploaded, or deleted.

Adding sprite selection in the inspector

I can’t believe I didn’t add this yet, but I added a new option in the inspector. If you have multiple sprites attached to an object, you can now select which sprite to use.

0
0
10
Open comments for this post

2h 30m 25s logged

Devlog 4

Recently I’ve been working on getting the scripting working. I’m using normal javascript with some added functions with something I call matuAPI. But I’m not here to show that right now. Rather, I think I should show some of the code of how my project works! Today, I want to talk about how I get multiple preview windows!


How it works

Every time someone double clicks an asset in the asset panel (which we can check by adding an addEventListener('dblclick', () => {});), a function called openPreview is called. When we call that function, we check to see if a preview of that file is already opened. We have a Map() called preview_windows, which contains all the previews that are currently open. If a preview for that file is already opened, we can simply just bring the preview back to the center of the screen.


Now, what happens if we don’t have a preview open? Then, we create a new div with the class name preview-window. Inside that div, we will have another div for the preview header (which contains the file name and the word “Preview”) and below that div, an img tag with the file image. If the file type is an image, then we set the src of the img to URL.createObjectURL(file). I haven’t had the time to add audio previews yet though…


What happens next? A function called centerWindow is called. It brings the preview div to a select random few points in the middle of the screen. This prevents all the previews from opening up in the same spot. Next, in order to make it draggable, we call a function called dragElement. It detects when the “handle” (the preview header from above) has a mousedown and mouseup event, using a document.addEventListener('mousemove', elementDrag); and document.addEventListener('mouseup', stopDrag);. In each of these functions, we change the position of the element that is being dragged when the mouse is down. We also call a bringToFront function, which just adds a predetermined number to the element’s z-index.


When the user clicks the close button in the header of the preview, we call the closePreview function, which is pretty simple. It removes the name of the file from the preview_windows map, and just deletes the preview.


There were some bugs while making this; renaming issues while a preview is open, the preview not closing when the asset is deleted, and some other elements that had to be added. But I’m pretty proud of the fact that it works and some QoL features that I added to it, like reopening the preview recentering it.


Thanks for reading this all the way down :) Next devlog, I think I’m going to plan on describing how scripting works!

0
0
10
Open comments for this post

4h 10m 39s logged

Devlog 3

Nodes now work!

I mean, you can now create them. Peep the screenshot below! I had to create a new .js file because script.js was getting a little crowded. It was getting a little hard to find stuff :p: I’m pretty proud of how it works, but I’m planning on improving it later.

Types of nodes

I’ve added 5 node types.


Groups

Groups are used to group other nodes together. Groups can hold other groups or objects directly under them, but no scripts, audios, or sprites.

Objects

Objects are like the main nodes you will use. They are you use audio, sprites, and scripts. They can stand alone or go under a group. As you can see, in the inspector, you can edit the x values, y values, width, height, etc.

Audio, Scripts, and Sprites

These 3 nodes require a parent object. They cannot hold anything. This is how you attach images, sounds, and code to your object!


What’s next

This devlog is a little short compared to my other ones, but I’m still proud of what I have made! This is probably gonna just end up as a prototype for the final node system. I’m planning on adding the option to lock width and height, letting users drag nodes around and locking them, and reordering nodes. Right now, you can just drag them around from group to group, but you can’t change their order.

After finishing the hierarchy, I’m going to move on to getting the coding part of the game engine working. I’m planning on using Javascript or a modified version of Javascript as matu’s language. Maybe I’ll call it matuscript heh

Next, the obvious choice is to work on simulating the game in the viewport. (I’m scared of this)

Finally, I want to work on save files and exporting. I still don’t know how I’m going to accomplish this (I’m even more scared of this)

Maybe I’ll distract myself by working on the looks of matu first.

0
0
4
Loading more…

Followers

Loading…