[Devember 2022] a space project | open source space game

Looks simple enough to implement. It would be cool if you could make a swept wing craft that retracts and extends the wings. Does not really make sense in space, too much, but would be cool.

1 Like

Yeah i like that folding wing design. It really doesnā€™t make sense in space, but it looks kinda cool. I could hook it up with actual box2D joints so it reacts to the world or you could shoot a wing off. Its just a video game, thereā€™s no law that says it has to make sense.

I have some ideas on paper for customizable ships. But thatā€™s one of the features I have cut for now to reduce scope. Only one ship till I get the rest of the engine working.

Started to add sounds effects.

2 Likes

I played around with some colors for better contrast, and I think I figured out the art style a little bit.

The first move was reducing the background textureā€™s pixmap format from RGBA8888 ā†’ RGBA4444

before: smooth 8888

after: stepped 4444


The noise now has a stepping instead of smooth transition that I think fits the art style a little better. And this reduced color pallet makes it easier to see foreground objects.


I also added a greyscale shader to fade to black and white when zooming out. This helps further with contrast.

To get the grey we calculate the average color for a pixel by sampling the r,g,b and divide by 3.

varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_blend;

void main() {
    vec4 color = v_color * texture2D(u_texture, v_texCoords);
    float grey = (color.r + color.g + color.b) / 3.0; 
    gl_FragColor = mix(color, vec4(grey, grey, grey, color.a), u_blend);
}

Then using a uniform to pass in the ratio of how much to u_blend the mix() between the original color, and black and white. The ratio in this case based on the zoom.

public void update(float delta) {
    CameraSystem cam = getEngine().getSystem(CameraSystem.class);
    float blend = cam.getZoomLevel() / cam.getMaxZoomLevel();
    spaceShader.bind();
    spaceShader.setUniformf("u_blend", blend);
    
    //renderStuff()....
}


I tried to avoid drawing a grid. But Iā€™m still struggling with frame of reference so I cracked and drew a grid to help judge movement and velocity.

I also want to keep the UI minimal for now. Thereā€™s a minimap, but Iā€™m hoping by letting the camera zoom out wide it lessens the need for a minimap.

Inverting colors with shaders is crazy easy too by setting the rgb values back to the inverse of themselves (1- value):

varying vec4 v_color;
varying vec2 v_texCoord0;
uniform sampler2D u_sampler2D;

void main() {
	vec4 color = texture2D(u_sampler2D, v_texCoord0) * v_color;
	color.rgb = 1.0 - color.rgb;
	gl_FragColor = color;
}

and looks pretty cool:

Im trying to keep my media small, playing with export settingsā€¦


Great resource for learning shaders:

3 Likes

Hmm, running into some trouble recording sound in OBS on Linux. Itā€™s not picking up desktop audio for some reasonā€¦

Summary

I double checked settings in pulse audio control panel. Tried killing and restarting the pulseaudio daemon.

Based on a search I ran this to trouble shoot:

$ pactl list | grep -A2 'Source #' | grep 'Name: .*\.monitor$' | cut -d" " -f2
alsa_output.pci-0000_00_1b.0.analog-stereo.monitor

This is what I had selected but it wouldnā€™t pick up any audio regardless of which app was playing audio.




Nothing is mutedā€¦had to look up sinks vs sources, but not really interested in fighting with this rn.

Based on another search I tried:

rm -f ~/.config/pulse/*
sudo killall pulseaudio  

Which was supposed to ā€œreset the settings when pulseaudio starts againā€? But this ended up making pulseaudio not want to start at all. Luckily I had the foresight to back those files up. Copied them back and pulseaudio started again. Still no desktop audio.

I gave up digging around all the sound settings and panels. So I just screen recorded on a different machine for now. Maybe ill move this question to the linux help thread. Anywhoā€¦


Sound FX!

I wasnā€™t sure what the asteroids should sound like when breaking apart. Given that sound cannot travel in vacuum of space, I figured why not have fun with it and just threw a sample in to get things started. In this case a single random piano note I exported from Ableton, which happened to be an F3.

Sound f3 = Gdx.audio.newSound(Gdx.files.internal("sound/f3.wav"));

The sound API provides control for volume, pitch and pan. So I randomized the pitch just to get an idea of what it sounds like:

public long asteroidShatter() {
    float pitch = MathUtils.random(0.5f, 2.0f);
    return f3.play(0.25f, pitch, 0);
}

For collision sounds, I wanted to set the volume of the sound based on the how hard the impact is with the other object.

In the Box2D physics contact listener, there is a postSolve() event:

  • This lets you inspect a contact after the solver is finished. This is useful for inspecting impulses.

Note: there can be multiple impulses, we want the strongest one.

@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
	// get highest impulse from impulse resolution
    float maxImpulse = 0;
    for (float normal : impulse.getNormalImpulses()) {
        maxImpulse = Math.max(maxImpulse, normal);
    }
	
	if (maxImpulse >= 1) {
        float damageThreshold = 15.0f; // impulse threshold at which to apply damage to entity
        SoundSystem sound = engine.getSystem(SoundSystem.class);
		if (maxImpulse < damageThreshold) {
			float volume = maxImpulse / damageThreshold;
			sound.impactLight(volume); //light impact with that gets louder with harder impacts
		} else {
			sound.impactHeavy(); // harder hit sound
		}
	}
}

(NOTE: postSolve() is also where I calculate damage from impact between bodies too. This is simplified to focus on sound. Also excluded are some other checks like the if playerā€™s shield is activated at time of impact, you take no damage and the impact is a different sound.)


I know sites like freesound exist, I just prefer to messing around in DAWS. And Iā€™ll make some more sounds later, but for now I actually have a friend who is interested in helping contribute some sounds, which is nice and helps me focus on the code.

Hereā€™s some gameplay destroying asteroids and bouncing around them with the physics. Itā€™s kinda like brick breaker in space:

These sounds arenā€™t the final pass, some are just place holders while figure out what to do with the sound design/implementation.

At first I had no intention originally of making the asteroids musical, but when I heard the randomized pitch in engine I thought it was kinda funny and kinda neat. Reminds me of amethyst blocks in minecraft.


I really like the result so I am goofing around and experimenting with stepping by 12 from 0.5-2.0.

The pitch range is [0.5f - 2.0f]. Which is half to double frequency. So in theory, we should be able get a range of 24 notes from 1 sample.wav

Or +/- one octave from the source frequency:

lower octave = [0.5 - 0.9?] (eg: 440Hz * 0.5 = 220Hz)
upper octave = [1.0 - 2.0] (eg: 440Hz * 2.0 = 880Hz)
int curStep = 0;
public long ascendingTone() {
	//  upper octave = 1.0 - 2.0 (eg: 440hz * 2.0 = 880)
	float step = 1.0f/12.0f; // = 0.08333
	float pitch = 1.0f + (step * (curStep-12));
	if (curStep < 12) {
	    //lower octave = 0.5 - 0.9583? (eg: 440hz * 0.5 = 220) 
        //step 11 -> 0.5f + ((1/12) * 0.5f * 11) = 0.9583
	    step *= 0.5f;//scale down 1.0 -> 0.5
	    pitch = 0.5f + (step * curStep);
	}
    
    //increase step
    if (curStep++ > 24) {
        curStep = 0;
    }
    
    return f3.play(0.25f, pitch, 0);
}

This was just quick and dirty, the pitch ratios are not ā€œin tuneā€:

Step -> pitch
0  -> 0.5
1  -> 0.5416667
2  -> 0.5833333
3  -> 0.625
4  -> 0.6666667
5  -> 0.7083334
6  -> 0.75
7  -> 0.7916667
8  -> 0.8333334
9  -> 0.875
10 -> 0.9166667
11 -> 0.9583334
12 -> 1.0
13 -> 1.0833334
14 -> 1.1666666
15 -> 1.25
16 -> 1.3333334
17 -> 1.4166667
18 -> 1.5
19 -> 1.5833334
20 -> 1.6666667
21 -> 1.75
22 -> 1.8333334
23 -> 1.9166667
24 -> 2.0

If I wanted to be in tune, could do a little 12-tone stepping calculation scaled by frequency ratio 2^(1/12), not linearlyā€¦ but it sounds neat anyways.

Iā€™ll explore panning to give sounds more spacial information. Sounds to the left should play in the left, and sounds in the right should play in the right. Also some sort of attenuation volume scaling so sounds from far away will be quieter than close sounds.


Thereā€™s a new hit effect when bullets collide with asteroids. Can add more particles later.

The trail left behind the player and behind projectiles ā€œbullet tracersā€ are a temporary debug tool. It shows path of travel, but with some additional information encoded via color: (engine state, shield state, when took damage, when successful block with shield).

Iā€™ll probably replace this trail with some sort of particle effect trails that fade nicely and help convey the change of velocity to illustrate motion.


Also Iā€™ve learned that MP3 is apparently not a good file format for seamless looping. It clips and cant seem to line up the waveform properly.

So most sounds will probably be WAV going forward.

4 Likes

Cool, I always like to see how people tackle sound design in games!
But I think that piano sample would give me a headache after a few minutes. :sweat_smile:

AFAIK most sound engines will decode MP3s in blocks, so you canā€™t start at a specific sample point like with WAV files. Maybe you could work around this by converting it to a WAV at runtime if you still need the reduced size.

2 Likes

Haha, yeah maybe itā€™s a little fatiguing. I just dropped these samples in to get things hooked up for now.

I think the default limit for decoded audio is 1MB. I am not too concerned about file size yet but thatā€™s good to consider. Noted.

3 Likes

I love the sound idea. I would say that I like the dissonant sound better than the dirty sound ratio.

2 Likes

I agree the true random pitch sounds better.

I think the amethyst block sounds from minecraft are quite pleasant so maybe Iā€™ll aim in that more ā€œsparkily gemā€ feeling. Or I could sample some sounds of rocks or big boulders smashing, idk yet.


I have some ideas for what I want to do with the resources that asteroids drop. I could do the standard:

  • iron
  • gold
  • silver
  • copper
  • etc, just grab some metals off the periodic table
  • gems: ruby,sapphire,emerald,etcā€¦
  • maybe thereā€™s icy asteroids and we need water?

Perhaps the sound of the asteroid can depend on its type or what resources it drops.

Iā€™m open to ideas.

1 Like

I realized I havenā€™t talked much about the gameplay itself yet. Which is probably important, given that it is a game. But first a little history.


I like to start on paper before touching code. Here are some of my old design notes:

Looks like at the time I was debating between either libGDX, slick2D, or LWJGL (which I always have fun trying to pronounce). I wonder if I would have chosen Godot if it existed back thenā€¦?

I had also wanted at the time some sort of good vs evil system with npcs, which was pretty much cut entirely due to complexity.

Why my own engine?
I started this project in ~2013. My previous project was a juiced up breakout clone in gamemaker 8, and by this time I was working almost purely in gml (game makerā€™s scripting language) because I liked having more control through code than the drag nā€™ drop actions/events.

On the side I also had started a simple tile-based engine based of TheChernoā€™s old engine series: https://www.youtube.com/@TheCherno because I was getting more interested in the lower level underlying technology.

When I had the idea for this game, I knew that some of the features I wanted to implement would probably be much harder to do in gamemaker. I didnā€™t want to limit my design or ideas based on the the constraints of someone elseā€™s engineā€¦

Then I stumbled upon some articles about the ā€œmagic of ECSā€ and the ā€œevils of OOPā€, and I was drawn by the flexibility. I Ģ¶wĢ¶aĢ¶sĢ¶tĢ¶eĢ¶dĢ¶ spent a lot of time reading about and stressing over different design patterns and clean code and code quality. Itā€™s easy to have ideas for features, but how to add them all without making a mess? How do I structure my program as it grows in scope and complexity? It certainly doesnā€™t help if you like to over-engineer things.

I have found that properly planning what I want to build first before touching code is really helpful.



(edit: added a few more)





It also allows me to identify certain problems before running into them during implementation or runtime.

For example: these pages are from a time when I was trying to sort out the some architecture issues. I mapped it out the class hierarchy / project structure to wrap my head around around the dependencies and coupling:

This helped me figure out where/how/why I was using certain objects and simplify the project a little.


A couple re-writes later and here we areā€¦ Now I have a more pragmatic approach of just keep it simple and follow best practices where applicable.

It is interesting to see what I have been able to implement so far compared to what I had originally planned. Some things have changed overtime, features cut because they were too complex, or didnā€™t make sense. Sometimes there is a technical limitation in the hardware or the software. Or even dealing with limitations in myself and my own abilities. Other times I am more excited by an idea itself than the execution.

Progress is definitely slow compared to if had decided to use a full engine like Unity or Godot. But ultimately I am glad I took the time to DIY as much as I could because Iā€™ve learned a lot from it.

Thankfully I also have the freedom to walk away from this project to focus on other things when I feel burnt out or overwhelmed. And that Iā€™m stubborn enough to keep coming back to it from time to time.


Right, so back to gameplay. Right now I have a problem of large empty universe, kinda boring and lonely.

Next up is getting the mining gameplay loop:

  • asteroids drop loot when destroyed
  • player collects loot
  • ship can carry X amount of loot in cargo until full.
  • player sells loot space station

Space Station:

At the space station the player can:

  • sell loot
  • repair ship
  • upgrade components on ship:
    • more health
    • better engine
    • etc
  • buy new components:
    • shield
    • hyperdrive for faster travel
    • different weapons
    • maybe a solar panel so you can recharge/heal when near stars or in direct light path of star (ray cast)
    • etc
  • buy/sell different ships (out of scope for now: I have some ship classes and types on paper)

Once you have loot and items, you need some flavor of UI/inventory. Iā€™ll draft some stuff on paper but I need to sort out some more details. Again, Iā€™d prefer to keep UI simple and minimal for now. I donā€™t like complex inventory management systems.

AI is partially implemented but disabled spawning to sort out some other stuff. The idea is AI ships will fly from planet to planet.

AI:
- fly between planets or stars
- can dock at space stations
- can mine asteroids
- passive by default, but will return fire when attacked

Some AI miners flying between asteroids mining locations and space stations. In theory you could be a space pirate, attack another miner to take their loot.

In my original design doc I had planned some sort of economy and trading system. Where resource X would be rarer in system A, than in system B. And with some travel you can profit. This has always felt out of scope till recently itā€™s coming into view, but I am not sure if thatā€™s even what I want to do anymore or how I want to implement it. I donā€™t want a really complex UI / inventory system.

Planned Content:

  • black hole at the center of the galaxy
  • worm holes or some sort of warp gate teleport type thing
  • AI battles
  • space creatures / bosses
  • scripted events / quests?
  • landing on planets (probably out of scope, will break down in future post)

While far from complete, Iā€™m forcing myself to make a demo build at the end of the January here so at least I can get some feedback on the controls and feel and people can poke at it. I know I said that last year, but it was really too incomplete and broken then. Iā€™ll see what I can get done in this final week (Iā€™ll be gone this weekend but Iā€™ll do my best)

Iā€™m in this awkward stage where I want to show certain things, and other things simply arenā€™t ready. But I canā€™t develop in a vacuum anymore and Iā€™ve already refined some controls for the ships based on some feedback people have given me. Which is very useful.

Down the road once I have a more complete gameloop and a little more polish Iā€™ll make an itchio page and start putting builds there.

I feel like Iā€™m finally hitting a turning point where I can start working less on the engine, and more on the actual game itself!

3 Likes

Hey, this is part of the creative process. It is better to get feedback early versus send out a viable product that no one wants, right?!

That must be a great feeling.

2 Likes

Itā€™s an interesting transition. Adding new mechanics and building out the world is usually a lot more fun than some of the other stuff.

For example, sometimes you spend a long time working on something internally in the engine thatā€™s important, but not very interesting work on. And often those under the hood tasks donā€™t have any obvious impact on gameplay or visually, so it can look and feel like your not making much progress. Those periods can feel slow and be difficult to get though. Especially without a clear goal or plan.

Thatā€™s certainly one way to do this, but itā€™s probably not the best.
For another a better approximation of actual luminosity values, try something like this:

float grey = 0.21 * sample.r + 0.71 * sample.g + 0.07 * sample.b;

As you can see, this is a weighted sum(You method is as well, but all the weight are 0.33. I hope this makes sense to you). And intuitively the green should contribute more to the total luminosity, since our eyes are more sensitive to green light.
(I know the weight add up to .99. I think this is intentional since it maps better to 0-255 without clamping)

Other than that, your game looks very cool. Itā€™s certainly ambitious, but you seem to make great progress. Keep it up! :stuck_out_tongue:

1 Like

Yep, makes perfect sense. I can see how green being more visible to our eyes than red is reflected in your weights.

How did you arrive on these specific values?


Also here is what the change looks like in engine:

The previous .33 weight:

With the weights you provided:

Itā€™s certainly darker and blacker overall results. Here is less zoom, less dark more mix:

I didnā€™t though of these values myself.
Itā€™s a well-known formula, but you can search google for it(keywords: luminosity greyscale shader).
Hereā€™s an article from 2009 comparing some methods:

2 Likes

Found those weights in the YUV YUV - Wikipedia

More color space stuff. Thanks!

1 Like

Item pick up magnetic/gravity effect prototype.


need to tune the forces a little based on distance.

Using collision filtering to differentiate between inner and outer circles:
image



Bug while implementing where i used the opposite angle and they were pushed away instead of sucked in:

3 Likes

Welp, here we are. I didnā€™t quite get everything I wanted in for this demo, but I am pretty happy with progress made the last 2 sprints.

I will keep working on this obviously, but as far as Devanuary goes Iā€™ll cut it off here. This is my official submission:

spaceproject_devember_enginedemo_20230131

There is a requirement to install Java (sorry). I will look into packaging a jvm the with build: Deploying your application - libGDX

If you donā€™t feel like running unsigned jars from strangers on the internet, source code here: GitHub - 0XDE57/SpaceProject at spaceproject_devember_enginedemo_20230131

Will sort out some better devops stuff later for future builds.


I put a lot of energy into fixing bugs and crashes instead of pushing more features in for this build.

Things that have not made it into this demo that I hoped for:

  • space station and docking
  • basic lighting / post-processing
  • laser and asteroid slicing
  • better destruction rules for asteroids
  • AI (AI spawning is currently disabled)

Known issues:

  • lack of gameplay: this is a basic engine demo
  • asteroids make extra pieces sometimes or spawn funny: #2
  • drops do not spawn correctly, this is a direct side effect broken origin caused by #2
  • magnet/gravity effect for sucking in drops needs tuning as I implemented this only just last night (they just get stuck in orbit around player or whip out passed the player when higher velocity)
  • thereā€™s nothing to do with collected drops yet (you will find a count below the health bar of how many you picked up. eventually to be sold at a space station)
  • missing sounds
  • camera needs work (disabled lerping due to running into some stuttering issues and framing, need to lead target, etc)
  • options UI for changing keybindings is really bad and broken
  • no in-game tutorial or explanation for controls
  • many more: see issues first
  • many other things in todo not in issues yet

I currently master everything in a plain text todo file, but its about ~1000 items long and only somewhat organized. So Iā€™m going to experiment with githubā€™s project organizing workspace thingy, and Iā€™m migrating items from my todo into that. Hopefully this tool gives me better organization and planning.


Anywho, here are the controls:


Notes and tips:

  • Some controls disabled; features not ready. Will break down in future post.
  • frame of reference and sense of scale can be confusing, zoom in and out to get your bearings
  • If you are going too fast to stop your ship before ramming into an asteroid, you can activate the shield to safely bounce off.
  • If you fly into a star, you can use the shield to protect your ship from burning up.
  • Minimap is off by default, M to toggle between [off, corner, full] and supports its own zoom level when mouse over.
  • all debug controls and rendering is left in because I think that stuff is interesting so feel free to poke around the debug menu options and have fun.
  • NOT LISTED IN CONTROLS: I left a very specific debug control in intentionally: Right-Click will spawn a new asteroid at mouse position. This is for you to play with / abuse / test and wont be part of regular gameplay.

Let me know what you think!

4 Likes

Java gets a lot of undeserved hate. Yes, I am biased.

All of the cool kidz do it thoughā€¦ thanks for providing the source code.

2 Likes

Java was one of the first languages I learned after gml and visual basic. I liked that I never had to to care about what operating system the user is running. Which seems to be true of more languages and engines these days but not so much 10 years ago.

I have been tempted to port to c++ ā€œbecause performanceā€, but Iā€™m not going to worry about ā€˜java is slowā€™ until I actually hit that wall (if I even do for a simple 2D game like this).

Different tools for different jobs. Iā€™d like to try Rust or Go Jai at some point.

3 Likes

Fixed some bugs. Been pretty busy with work, will try to release update this weekend.

2 Likes