Jump to content

Procedural Generated 2D Starfield


yahiko
 Share

Recommended Posts

For a game project I am working on, I would like to implement a 2D starfield as a background.

I do not want to deal with static tiles, since I plan to slowly animate the starfield. So, I am trying to figure out how to generate a random starfield for the entire map.

I feel that using a uniform distribution for the stars will not do the trick. Instead I would like something similar to the screenshot below, taken from the game Star Wars: Empire At War (all credits to Lucasfilm, Disney, and so on...).

595256e1ef97a_StarWarsEmpireatWar06_27.2017-14_58_01_01.thumb.png.790912fdda268cc3003ab8d46670080f.png

 

Is there someone who could have an idea of a distribution which could result in such a starfield?

Any insight would be appreciated ;)

Link to comment
Share on other sites

hi with pure js 


 


function random(min, max) {
    var nMax = max;
    var nMin = min;
    var aleat = Math.floor(Math.random() * (nMax - (nMin - 1))) + nMin;
    return aleat;
}

function Star(x,y){
	
	this.pos={x:x, y:y};
	this.alpha = 1.0;
	this.up=false;
	this.adder=random(10,40);
	this.limit = 50;
	
	this.size={w:random(1,3), h: random(1,3)};//variable size
	
	if(random(1,2) == 2){
		this.up=false;
	}else{
		this.up=true;
	}
	this.red = random(0,255);
	this.green = random(0,255);
	this.blue = random(0,255);
	
    this.speed={x:-5, y:0}
	
}
Star.prototype.update=function(){
	if(this.up){
		this.adder+=1;
		if( this.adder > this.limit){
			this.up = false;
		}
		
	}else{
		this.adder-=1;
		if( this.adder < 1){
			this.up = true;
		}
		
	}
	
	this.alpha = this.adder / this.limit;
	
    //move,  to left
    this.pos.x += (this.speed.x);
    if(this.pos.x < -10){
    this.pos.x = canvas_w+10;
    this.pos.y = random(0,canvas_h);
}
}
Star.prototype.draw=function(){
	ctx.clearRect(0,0,canvas_w, canvas_h);
	ctx.fillStyle = "rgba("+this.red+","+this.green+","+this.blue+","+this.alpha+")";
	ctx.fillRect(this.pos.x, this.pos.y, this.size.w, this.size.h);
	
}

//creation of stars

var totalStars=100;
var canvas_w=800, canvas_h=450;

var i=0, j=0, k=0;

var stars=new Array();

for(i=0; i<= totalStars; i++){
	stars.push(new Star(random(0,canvas_w), random(0,canvas_h)));
}

//in update of gameloop
for(i=0; i<= totalStars; i++){
	stars[i].update();
}

//in paint of game loop
for(i=0; i<= totalStars; i++){
	stars[i].draw();
}

 

Link to comment
Share on other sites

I made a little starfield generator a good while ago, its a little old but still works fine, I've used it a couple of times although it needs a bit of perf work. https://github.com/mattstyles/pixi-starfield

I can't remember exactly how it works but its uses simplex noise to create a distribution and then places stars randomly on to that heightmap using the noise to help define the colour profile of each star, so, effectively (I think) its a uniform distribution across the area but some areas are just brighter than others. Each star has transparency and its only colour profile, which uses bezier easing to be more effective. 

The layered example shows a parallax effect, as you can set any texture you like for stars some layers use large cloud textures to hint at nebulae, clusters etc, again, the colour profile of these clouds can be configured and tend to show up where stars are thicker, which is pretty much realistic from what we can see in the sky.

It's tileable by reusing the pool of stars and shifting them when they go out of view to be recreated at a random location about to come in to view (again, I think, it might just transpose them across the screen), this means the sky continually changes but it all averages out so dense areas stay dense even if stars do change location as they still all conform to the consistent infinite simplex noise heightmap, this means if you stuck a planet at [200,200] and it was in a dense cluster, it'll remain in that dense cluster.

I wouldn't necessarily use that starfield lib as is, it needs some perf work (most of which would be easy to do) but it might give you some ideas about how to approach it.

Link to comment
Share on other sites

I've been quite busy this week, so I haven't been able to really work on this project.

However, I've succeeded to implement a first experiment of a 2-layer starfield as @bubamara suggested, based on @diyo-games's JavaScript code, although I've used TypeScript and Phaser.

starfield.gif.a0b1c84afb4205aa14ee186005c7a610.gif

For information, I've implemented a cache where I draw on a hidden canvas before displaying it.

I had a look at @mattstyles's repository, but I wasn't able to make it work, unfortunately. I also had a glance at the source code, but I would have needed more time to understand.

Anyway, as a begining, I find this result quite promising. A uniform distribution is not an issue after all since stars seem quite scattered with some voids and clusters.

I will try to improve this demonstration a little bit by using HSL colors instead of RGB, and chosing colors according to a gaussian distribution and not a uniform distribution, which is not realistic in such a case.

As a roadmap, I would like to implement some special objects like comets and supernovae. Also, I would be interested to have some hints to produce some gas clouds as we can seen below:

s-l300.jpg   ff6a19a808dc5888a0c99c7810c0776a.jpg

Link to comment
Share on other sites

To implement clouds I just drew a number of different cloud textures (using photoshop and largely mucking around with filters->render->clouds and difference clouds, then cutting out sections, smoothing, etc etc greyscale) and displayed them in the 'busiest' areas of the star field, rotating/scaling/colouring based on some heuristic. With the correct levels of alpha set they blend in to each other and usually look good enough without being too much of a perf drain. They end up looking like your first image (blue) rather than the more complex formations from your second image (red), but you could probably get close to that with more work on creating decent textures up front and not get into the complexity of trying to programmatically create cloud textures.

Link to comment
Share on other sites

Conceptually its pretty similar to a particle emitter, very similar if you tied the lifecycle of a particle to camera/player movement rather than time i.e. often a particle moves from one state to another based on time, you might want your stars pretty static so they only change position on the screen based on the movement of some observer (camera), they still effectively move from one state to another though so in the sense that you're managing the differential between those states, yeah, its similar to a particle emitter.

I expect many particle emitters could be configured to create a starfield-type effect, whether they'd do exactly what you want is a different matter.

 

Link to comment
Share on other sites

Hello,

I'm back with some news about my project. I've brought some improvements to the star field generation.

Colors now use HSL instead of RGB. Also, I choose them over a Gaussian distribution giving the star field a more realistic aspect. All stars of a given layer now share a same "tone".

I've encountered some issues with Phaser which seemed to leak into memory above 700 stars --- and drew me lines instead of circles. :D

So, I changed to Pixi.js which is hopefully quite close to Phaser and seems more reliable since there is no more glitches for a large number of stars.

To give an overall better aspect, I've applied a blur filter to the whole scene. At first, I've tried to blur stars one by one but this is really inefficient...

You can see below a static overview. The animated GIF was too big to upload ^_^ 

starfield20170708.png.126fbb4248c9536f4bfab9dbc7421d4b.png

From a performance point of view, instead of drawing and redrawing stars each frame, I turned them into sprites. This improved dramatically my FPS.

I've also added a quick and dirty GUI on the right side in order to be able to play along with various parameters. I've uploaded an online version here: http://yahiko.developpez.com/apps/Starfield/

For the time being, I hadn't got the time to implement comets, supernovae or gas clouds, but this is still in the roadmap. I'll let you know. :ph34r:

Link to comment
Share on other sites

Some progresses have been made since the last time.

Comets are now implemented. I use a 500-particle system which is, I think, a good compromise between performance and resolution.

I've replaced the blur filter which cause an undesirable loss of brightness by a bloom filter which on the contrary, enhance stars' brightness, which is what I wanted.

More importantly, I have implemented a first attempt of a gas cloud based on the simplex noise shader --- inspired by the many examples available on shadertoy.com.

I find the results quite convincing although there is room for improvement. This is not really possible for the moment to control the shape of the gas cloud, and I can hardly define the main color of it. I guess I need to dig more into the math of this shader... ^_^

starfield20170712.png.11a1369b6e840a485e39ac970febf474.pngstarfield20170713.png.824ec1653f37a205eb2bd5e2ba38831f.png

Feel free to try it onlinehttp://yahiko.developpez.com/apps/Starfield/

To make it works, with the gas cloud and the bloom effect, your browser and your GPU (or integrated Intel Graphics) need to support WebGL.

Any feedback and suggestion are welcome to improve the overall aspect.

Cheers! :)

Link to comment
Share on other sites

Love those comets. n1,

there is a great tutorial over at http://wwwtyro.net/2016/10/22/2D-space-scene-procgen.html i'm not using shaders though and still managed to get something i was happy with. first i generate a radial plasma gradient (but you can use whatever texture) and use it to render a simple set of particles bound to the screen space which works for me. just to show it can work here's a demo.

WIP the nebulae has a bit more speed than it will in the final but i really wanted them to move.

ezgif-3-f6fd697347.gif.92aefee5953bba5c0282ce93e8fc8b56.gif

Link to comment
Share on other sites

I really like the fact your nebulae can move :)

Your result are nice already and your project looks promising! I will have a closer look into plasma gradient. Seems interesting.

For the tutorial, I've just discovered it couple of hours ago. This could has saved me a lot of hours if found it sooner... But, I can see where I can improve some part of my implementation.

Don't hesitate to let me know about your progress :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...