Flashy Stuff feat. Loop

Flashbangs are working.

I have the patrol bots hooked up to throw them based upon an enumeration (Which I dont like, I’d rather a subclass but I shot myself in the foot earlier on).

I just hijacked the reload animation and basically said “if you’re a grenade bot, reload, and instead of throwing a mag up throw a flash-bang”. Pretty stupid for now but its a good proof of concept, the shakyness is because I half implemented physical animations to handle bot hits. I’m still not happy about that, I want to move to a fully unreal animation setup because my animations are so simplistic but that’s another avenue I gotta go learn.

Also

Some Texture Painting / Raspberry Pi fun

Attempted to add some color to the zapper I showed earlier. I’m not 100% enthusiastic about the job I did but I still like some of the ideas I have here.

For the record this is how you setup a shader in blender for texture Paint:

Essentially you make a shader that you like as your “base”, then make an image that is zero alpha. Then you tie the alpha of the texture into a color mix node, that way when you paint on the texture it will swap in the information on the image to the shader. If I wanted to get REALLY creative here I would add in something like a chipping algorithm based upon the tangent of the base model so you would get a “worn” look to everything.

The potato cannon button I think came out fine, the wires could have used a bit more slack (or maybe some stables holding it down).

The front of the cannon I tried adding some scorching but honestly I botched that portion so it looks more like someone dipped the front in soot and smeared it back.

The bat handle is a bit too cartoony. The wrap needed to be tighter but I already applied the screw modifier onto the object so I was stuck with this. I’ll probably remake this if I keep the same idea.

The shoulder brace bike tire I’m weirdly happy with (minus the un-beveled edges), making a tire is surprisingly difficult in blender (for me atleast).

The pylons in the back I think look kinda cool, but they seem crazy out of place to the rest of the weapon. They don’t have that “junkyard” kinda look I was going for (also without lighting its hard to see the green emissions)

The can and the junction box are fine, I’d want to add a label to the can and some screws to the junction box.

In other news I spent 3 hours debugging my asus bt500 (https://www.asus.com/us/networking-iot-servers/adapters/all-series/usb-bt500/) on a raspberry pi 5 so I could get my xbox controller hooked up to run steamlink (which recently was released for the raspberry pi 5 arch https://help.steampowered.com/en/faqs/view/6424-467A-31D9-C6CB). I’m using this kit https://www.amazon.com/CanaKit-Raspberry-Starter-Kit-PRO/dp/B0CRSNCJ6Y/ref=asc_df_B0CRSNCJ6Y?mcid=499475e052c83be5a802a944f85cf088&tag=hyprod-20&linkCode=df0&hvadid=693601922380&hvpos=&hvnetw=g&hvrand=8182359702763456621&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=9002000&hvtargid=pla-2281722246870&psc=1 which I got on sale at microcenter. My thought was getting a fan would be better for long sessions of video decoding on steamlink.

I only wanted a bluetooth adapter because my xbox controller would have crazy delay to the raspberry pi 5 integrated bluetooth adapter, I only bought a bt500 because it was at microcenter and it was kinda cheap. Turns out the realtek chip inside of the bt500 isn’t natively supported by raspian (or linux really). After debugging for like 3-4 hours, I had a thought that maybe the cana kit fan was blocking the bluetooth signal, so I removed the fan tried the native bluetooth on the raspberry pi and everything worked perfectly.

tl;dr : I spent extra money to give myself more problems

Zapperz

Not sure what this is but I think I might keep rolling and texture it to see where it can fit in to future projects.

Other angles:

The pole out the side is supposed to be the end of a baseball bat, the curve underneath I wanted to be some kind of road tire.The sights are a soup can with a nail poking underneath.

….What is it?

I made this thing:

I don’t know what it is but its neat.

The column+coil is built around taking the animation frame counter, doing some math to make a sine-wave and using that as a blend factor between a few colors. Here’s a better zoom.

Not much more to show of this, the base is too shiny IMO but I was surprised how easy it was to make dynamic textures in blender. The volume aspect I hooked up just to see what it would look like and I dug it. In the future I should learn a bit more about how that plays into things but for now I’m happy with my cheap smoke.

I Built A TF2 Mod (Built meaning compiled)

I have tried to build a source engine mod probably 5-6 times since I started programming in late 2000s early 2010s and I’m finally ahead of the curve and I was able to get a mod built before valve did something that wasn’t in the public c++ repos that broke everything! (See https://github.com/ValveSoftware/source-sdk-2013/tree/master)

This is not an accomplishment but I’m happy it’s possible. Will I do anything with this? Probably not….

What happens when I launch the mod??

uhhggg…. I could figure this out but honestly if I’m diving into source I’d rather start with source 2 and cs2. But there’s a 10 year old part of me that longs to make a source mod, put it on moddb, start a dev blog, abandon the mod, notice another team picked up my mod, start a mod that competes against the original and fall into a deep depression when the original mod team gets hired by valve.

One can only dream.

Unreal Stuffs

I’ve been playing too much xcom and I felt like my c++ skills were waning so I thought it would be a fun quick project to quickly spin up a turn based squad commander system.

There’s probably a way to make these go away…

The camera

First thing that is distinctive about xcom is that it’s an isometric game, therefore the camera is fixed above the level and travels along various levels of the map. To achieve this effect I made a quick camera pawn that does two things: Ray traces to a fixed height above the ground and constantly aligns itself to a specific pre-set orientation.

Instead of going crazy with pre-mades I just threw a camera component onto a pawn class with a few pre-set parameters.

Header code:

  //CLASS BLUEPRINT EXPOSED PROPERTIES
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float BaseHeightOffGround;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float CameraAlignmentRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float HeightCorrectionRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		FRotator BaseCameraRotation;
	//END CLASS EXPOSED PROPERTIES

	//START COMPONENTS
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PrimaryCamera", meta = (AllowPrivateAccess = "true"))
		UCameraComponent* PlayerCamera;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Collision", meta = (AllowPrivateAccess = "true"))
    	UCapsuleComponent* CameraCollider;

The tick function I have two lerps: 1.) for the current camera orientation and 2.) for the result of a down racytrace + a fixed offset.

//Ensure we're rotated properly to the desired world rotator that the user specified
    FRotator currentRot = GetActorRotation();
    FQuat newRotation =  FQuat::Slerp(currentRot.Quaternion(), BaseCameraRotation.Quaternion(), CameraAlignmentRate*DeltaTime);
    SetActorRotation(newRotation);
    // Get the world object
    UWorld* World = GetWorld(); 
    // Check if the world exists
    if (World)
    {
        FVector Start = GetActorLocation();
        FVector End = Start + FVector::DownVector * BaseHeightOffGround*10.0f;
        FHitResult Hit;
        FCollisionQueryParams QueryParams;
        QueryParams.AddIgnoredActor(this); 
        bool bHit = World->LineTraceSingleByChannel(
            Hit,                
            Start,             
            End,              
            ECC_Visibility,     
            QueryParams         
        );
        if (bHit)
        {
            FVector newWorldPos = FMath::Lerp(Start, Hit.Location + FVector(0,0,BaseHeightOffGround), HeightCorrectionRate*DeltaTime); 
            DrawDebugLine(
                GetWorld(),
                Start,
                Hit.Location,
                FColor(255, 0, 0),
                false, -1, 0,
                12.333
            );
            SetActorLocation(newWorldPos);
        }
    }

THE RESULTS!

Note: the red line is just for my debugging purposes. Also the camera will not be visible in game.

The DSP engineer in me is balking at the casual use of a delta time and a linear interpolation. But, we’re on a PC running at low data rates (60hz!?!? pfffffff I could get this running at 24khz) and variable frame sizes so while I keep thinking “I could optimize this to be less MIPS” I think I’ll just press on…

Commanding/ Game structure

In xcom the turns are play out that you select a squad member, choose their action, move to the next squad member, choose their action, until you have no more squad members, then your turn is over.

Now there’s a few ways I could implement the squad mechanics. Specifically the way that each squad member gets controlled and how the player controller interacts with them. I could have the user’s controller re-posses each pawn upon selecting them (which might save memory but increase the work upon possession). However, I would still need to perform path finding to move the character to a specific location. Instead I think the way I want to play it is to have every squad member owned by an AI controller that receives broadcasts from the player controlled camera pawn. Below is my rough diagram (I think there’s a gamemode state in there that I need to throw in but generally I think this is fine)

www.drawio.com FYI

In addition to handling the general flow of the game I think the other side is that this sets the game up for multiplayer from the start.

The command/game state messages I think I’ll probably make delegates in the game mode that the controllers can subscribe to. Then the deaths of squad members and selections I think I’ll push to to the controllers? My thought here is:

I’ll probably jump back on this tomorrow and start coding up the events and perform in a test or two.

Gadot Bro a.k.a. Wonder Wonder Woman game engine a.k.a. Side project to a side project

I started messing with Gadot (https://godotengine.org/) to fulfill the free-form open source activist in me (also I have a friend making stuff in Gadot).

So I started messing with the 3d side but the goal is for a more metroidvania type game. So I moved into understanding the 2d asset pipelines a bit better. The way I want to handle this is to:

  • Make a spritesheet(s) with four different animations: Idle, walk, jump, land
  • Make a character using the sprite-sheet with simple controls
  • Stretch goal- Add landing and walking smoke effects

Making spritesheets has gotten so easily since I was making simple games in XNA (15ish years ago damn…) now you can do everything in browser. I’m using https://www.piskelapp.com which is very fast and reliable for dumping a .png for a sprite sheet.

I’m going with a stick figure. I’m cool with jank walking but as long as you get four frames I you’re good (https://en.wikipedia.org/wiki/Walk_cycle). My finalized sprite sheet:

First three two frames are idle (just a simple bob). The next four are the jump/land cycle, the rest are walking (which I can invert for each direction in gadot).

Gadot has a REALLY good sprite sheet importer:

It lets you chop, then select which frames to import. In that way you can keep 100% of the sprites in one huge sprite-sheet and not worry about flipping between files at runtime (which in reality isn’t a big issue but I imagine you’re going to hit performance on low ram platforms with 1000+ pngs loaded in memory).

The animation editor once you get frames in place is SUPER easy and lets you quickly edit and test spritesheets as needed:

All of these get stored inside of your “AnimatedSprite2d” instance that can be selected via sprite frames property:

Now the scripting in gadot mirrors unity (and unreal kinda) where everything has a setup and loop function that you edit to handle internal logic to your “Nodes” (which are called actor and gameobject in unreal and unity respectively). Gadot doesn’t have a nice state machine editor like unity or unreal so you need to program it up yourself. The design of the simple character is actually expecting you to do this so there’s there’s state and utility funcitons in both the character and sprite classes that let you do this easily:

extends CharacterBody2D

const SPEED = 300.0
const JUMP_VELOCITY = -400.0
@onready var _animated_sprite = $AnimatedSprite2D
#AnimationStateMachine
var startJump = false
var isFalling = false
var endJump = false
var isWalking = false

func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta
		startJump = false
		isFalling = true
	elif isFalling and is_on_floor():
		endJump = true
		isFalling = false
	elif endJump and is_on_floor():
		endJump = false
	else:
		endJump = false
		isFalling = false
		
	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		startJump = true

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction := Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * SPEED
		if(absf(velocity.x) > 0):
			isWalking = true
		else:
			isWalking = false
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		if(absf(velocity.x) > 0):
			isWalking = true
		else:
			isWalking = false
	move_and_slide()
	handleAnimationStateMachine()

func handleAnimationStateMachine():
	if startJump:
		_animated_sprite.play("Jump_start")
	elif isFalling and _animated_sprite.animation_finished:
		_animated_sprite.play("Jump_loop")
		startJump = false
	elif endJump and  _animated_sprite.animation_finished:
		_animated_sprite.play("Jump_end")
	elif isWalking and _animated_sprite.animation_finished:
		_animated_sprite.play("Walk")
	else:
		_animated_sprite.play("default")
		endJump = false
		isWalking = false

If you have no idea what this is doing essentially its:

Final result:

So I’m pretty confident here that if someone threw me a bunch of sprites/2d art I could go ahead and make a game. Gadot has the same issues as unity where the structure is much less defined than Unreal. Therefore its crazy easy to prototype but scaling up will take more developer discipline to prevent Node spanning bugs and state issues. In my head the rough hierarchical structure of any 2d sidescroller would be:

The way to read this is that the controller points to the controlled. So the game master controls everything the scene master controls characters and cut-scenes etc. With this structure way you don’t get confused with race conditions etc. If you’re a lower level object that wants to initiate a high level event you’ll be forced to request up the chain (i.e. an npc that the player presses use on will send a request to the scene controller to start a cut-scene, which will then send a request to the game controller which then can trigger the cut-scene player). It seems confusing and over-engineered but if you consider the alternative you would need everyone to align to some other kind of mental model, which in my opinion can be crazy painful to handle and leads to a BUNCH of crunch.

Leaning Updates

(Writing as I’m doing this fyi) I wanted to re-write the leaning in the game. Right now the movement is all very snap, which has some skewing to it but i wanted a more gradual lean in.

Event graph level

(Normally I would use https://blueprintue.com, but wordpress is weird about iframes)

Now you can see here the process is, press button, move to desired input. My first thought was to throw in the delta seconds of the last frame, add a rotator and vector interpolation block and be done with it, however, Unreal’s input system is actually made for this. If you look at the top blueprint I have a few branch statements that was thresholding based upon the input value. Instead I’ll use that input value to skew between the lean position and the rest position.

My lean action by default is a 1-d float which is cumulative, which should mean that as I press the lean keys (Q+E) the value of the lean action (the Axis value line from the first plot) should increase as the buttons are held down.

Therefore, if I just use that value to skew between the lean position and rest position I should be good….

I was not good

What I described above is TOTALLY not how this works. Advanced input seems to not hold any kind of state from the previous frame unless you’re using defined curves. For example there is a “scale by delta time” modifier that works but it takes whatever the current input is and multiplies it by the frame time. This can be useful but my goal here was to avoid adding another accumulator within the player blueprint class. You can add an exponential curve but that’s just a modifier to the input values. I don’t think there will be a good way here other than adding a “currentInputValue” modifier and having it decay at a fixed rate…

This is one of those situations where I shot myself in the foot for using blueprints, however I think there’s enough syntax and other bugs that I saved myself from that I don’t care that much. For example In matlab (which I use a bunch at work) this problem can be solved via:

startPos = [-10 -20 -40];
endPos = [-10 20 40];
restPos = [-10 0 60];
inputAxis = linspace(-1.0,1.0,3);
[iAx iAy iAz] = meshgrid(inputAxis,inputAxis,inputAxis);
[xOut yOut zOut] = interp3([startPos;restPos;endPos],CURRENT_INPUT_VALUE,iAx,iAy,iAz);

I think unreal can do this with curves but my head moves towards code when we get to 2+ dimensions. But honestly this is me overthinking on coffee at this point, I’ll just throw it in with another accumulator and some alpha smoothing (https://en.wikipedia.org/wiki/Exponential_smoothing, which I believe is implemented in https://dev.epicgames.com/documentation/en-us/unreal-engine/BlueprintAPI/Math/Smoothing/WeightedMovingAverageFloat)

Attempt #1

First thing I is that I embraced curves:

Which was so simple I’m confused why I didn’t start with these. The only hitch I had is that it was annoying to find the “getVectorValueFromCurve” block. If you just blindly add a curve class or runtime curve class this isn’t exposed. Now the results:

This worked but now I’m hitting issues with state management. The rough way the Unreal input system works is:

if(currentState == buttonPressed && previousState == buttonReleased)
{
   Trigger(inputValue);
}
elseif(currentState == ButtonReleased && previousState == ButtonPressed)
{
   Ongoing(inputValue);
}
elseif(currentState == ButtonReleased && previousState == ButtonPressed)
{
    Complete(inputValue);
}else
{
    //DoNothing
}

Which essentially means that putting the logic attached to button presses is a fools errand. I need to move it out to the tick function, or I need to figure out how to modify the states above to keep firing the “completed” state.

Attempt #2

I tried messing with advanced input and hit the same state issue. I was hoping I could set the trigger to also be released but it never hits more than once.

No dice…gotta push the input value smoothing and the lean function to the delta. This will require another variable to handle the previous input value of the lean buttons. This might mess up the way I visualize the math but lets see what happens.

Attempt #3

This seems to be the best lean method. Essentially I needed to add one more var to handle the current value of the input and keep the same one that defined the previous variable. Below is the blueprints.

Tick event is the input to the left

Pretty simple at the end of the day. Hard part about this stuff is never what you’re doing its always that transition from what you’re doing into the mental model that the unreal devs used.

Finally my management failure…

Which doesn’t really matter too much because I’m working solo, without a server to push content to. However its just bad practice to not protect yourself from silly confusing mistakes (which will increase as you get to the end of development).

Next goals

1.) Add a flashbang and grenade robot (look back in my notes I have a flashbang and m67 already modeled).

2.) Add a new weapon

3.) Add a humanoid character that rides the robots?

Chaos Physics 1…me 0

Spent a bunch (like 1-2ish hours) of time trying to get the chaos physics working with the tree and…

It kinda works but the issue comes into the in game interaction. The damage levels seem to be weirdly arbitrary and aren’t assigned to a root bone but the pieces themselves Also the definition of “damage” seems to be just a number that gets exceeded in a fixed amount of time. I could probably figure this out with another day or so of digging but I’m starting to get fixated on this rather than just straight up making the game. However, I’m going to go through my experience just to give an intro/document for myself in the future.

Making a destructible object

This part actually wasn’t that hard, essentially you just drag/drop a mesh in. Flip to the “fracture” mode and click new. Then you start using the slicing tools on the left hand side to cut apart the mesh, then you select sub-part of the mesh and cut again.

This creates a tree of destructible on the left hand side where each “level” is a root piece that has child pieces.

So the idea seems to be you break the root the rest will break off. However, that’s the part I’ve been stuck on, there’s damage settings that seem to not work the way I would expect. Either way I’m moving the goal to making more weapons and enemies.

Loop-gardium Loop-iosa

Wanted to make a 200-ish bmp beat but I got bored and glitched them the hell out.

You should NOT do this for any reason, normally it makes a horrid clippy sound, in this case I compressed and filtered it so it wasn’t that bad.

The synth-y part is an Abelton meld preset with an up arpeggiator at the front.

I might re-make this guy with the same synth but better, less bugged out drums but I kinda wanna make the tree model break apart the way I wanted in game I’m making….I’ll play it by ear based what I’m feeling tomorrow.