pythonpygletprocedural-generation

planets created from 1d perlin noise terrain look weird


i am trying to make planets using pyglet but they end up looking like stars result

here is my code also i need a way to convert a batch to a sprite (to move it easily)



import pyglet
from pyglet import shapes
import opensimplex
import math
import time
brtd = 0
######## planets###########
class planetobj():
    def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home  never will thy become infected with the virus that has a closedcure"):
     self.seed = seed
     self.age = age
     self.position = position
     self.color = color
     self.name = name
     self.description = description
    def gplanet(self,size):
     opensimplex.seed(self.seed)
     done = 0
     xc = 0
     c = 0
     self.terrain = []
     start = opensimplex.noise2(x=0, y=self.age)
     while (done == 0 or xc < 50) and not xc > 100 :
         xc = xc + 1
         c = c + size
         value = opensimplex.noise2(x=xc, y=self.age)
         self.terrain.append(value * size)
         if xc > 50:
          if math.floor(value * 100 ) == math.floor(start * 100):
             self.done = 1

    def mkplanet(self, x,y):
      self.batch = pyglet.graphics.Batch() 
      corner1 = (x,y)
      self.trias = []
      counter = 0
      cornerback = [0,0]
      for i in self.terrain:
            counter += 1
            radi = (360 / len(self.terrain)) * counter
            radi2 = (360 / len(self.terrain)) * ((counter + 1 ) % len(self.terrain))
            theta = self.terrain[(counter +1 ) % len(self.terrain)]
            corner3 = (x + math.sin(radi) * ( i )  ,math.cos(radi) * ( i ) + y )
            corner2 = (x + math.sin(radi2) * ( theta )  ,math.cos(radi2) * ( theta ) + y )
            self.trias.append(shapes.Triangle( x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
############ basic game logic  & rendering ###########
scr_X = 400
scr_Y = 300
window =  pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch() 

earth = planetobj()
earth.gplanet(200)
planets = []
planets.append(earth)

earth.mkplanet( 50 ,50)
@window.event
def on_draw():
    window.clear()
    earth.batch.draw()
pyglet.app.run()

i tried changing the values that get divided by 'len(self.terrain)' but i could not find out how to make the planets look round

EDIT thank you kind commenter (and also the rest of stackoverflow)

now i made a working version feel free to use it '''

import opensimplex
import math
import pyglet
from pyglet import shapes
pi = 3.1459
debug = 0
class planetobj():
       def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home  never will thy become infected with the virus that has a closedcure"):
        self.seed = seed
        self.age = age
        self.position = position
        self.color = color
        self.name = name
        self.description = description
    def gplanet(self,size):
     self.batch = pyglet.graphics.Batch()
     opensimplex.seed(self.seed)
     done = 0
     xc = 0
     c = 0
     self.terrain = []
     start = opensimplex.noise2(x=0, y=self.age)
     while (done == 0 or xc < 50) and not xc > 100 :
          xc = xc + 1
          c = c + size
          value = opensimplex.noise2(x=xc, y=self.age)
          self.terrain.append(value * 10 + size)
          if xc > 36:
              if math.floor(value * 100 ) == math.floor(start * 100):
                  self.done = 1

    def mkplanet(self, x,y):
        global debug
        corner1 = (x,y)
        self.trias = []
        deltatheta = 360 / len(self.terrain)
        for counter,i in enumerate(self.terrain):
            theta1 = ((deltatheta * counter)/180) * 3.1459
            theta2 = (deltatheta * (counter + 2)/180) * 3.1459
            radius = self.terrain[counter]
            print(str(theta1) + "," + str(theta2))
            radius2 = self.terrain[(counter + 1 )% len(self.terrain)]
            corner2 = (x + radius2 * math.cos(theta1), y + radius * math.sin(theta1))
            corner3 = ( (x + radius2 * math.cos(theta2)), (y + radius2 * math.sin(theta2)))
            self.trias.append(shapes.Triangle(x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
            if debug == 1:
             self.trias.append(shapes.Circle(  corner2[0], corner2[1], 2, color=(255, counter % 255, 40), batch=self.batch)     )
             self.trias.append(shapes.Circle(  corner3[0],  corner3[1], 2, color=(255,255, 255), batch=self.batch)     )
            

############ basic game logic  & rendering ###########
scr_X = 400
scr_Y = 300
window =  pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch() 

earth = planetobj()
earth.gplanet(150)


earth.mkplanet( 250,150)
print(earth.batch)
earth.batch.draw
@window.event
def on_draw():
    window.clear()
    earth.batch.draw()
    print("drawing")
pyglet.app.run()

'''


Solution

  • OK, I've corrected your trigonometry, but there are some other issues. The random values you get back from the noise generator are between -1 and 1. You are then multiplying that by the planet size, which gives you wild variations from wedge to wedge. What you want is to have a basic wedge size, which you use the noise to adjust bit by bit. Here, I'm saying that the noise should be 3% of the wedge size (size/30).

    I didn't want to download opensimplex, so I've used a uniform random number generator. I'm also using matplotlib to plot the triangle, but see if this is closer to what you intended.

    import math
    import random
    import numpy as np
    import matplotlib.pyplot as plt
    
    class planetobj():
        def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=""):
            self.seed = seed
            self.age = age
            self.position = position
            self.color = color
            self.name = name
            self.description = description
    
        def gplanet(self,size):
            done = 0
            xc = 0
            self.terrain = []
            start = random.uniform(-1,1)
            while (done == 0 or xc < 50) and not xc > 100 :
                xc = xc + 1
                value = random.uniform(-1,1)
                self.terrain.append(size + value * size / 30)
                if xc > 50 and math.floor(value * 100) == math.floor(start * 100):
                    done = 1
    
        def mkplanet(self, x,y):
            corner1 = (x,y)
            self.trias = []
            deltatheta = 360 / len(self.terrain)
            for counter,i in enumerate(self.terrain):
                theta1 = deltatheta * counter
                theta2 = deltatheta * (counter + 1)
                radius = self.terrain[counter] 
                corner2 = (x + radius * math.cos(theta1), y + radius * math.sin(theta1))
                corner3 = (x + radius * math.cos(theta2), y + radius * math.sin(theta2))
    #            self.trias.append(shapes.Triangle( x, y, corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
                self.trias.append(( x, y, corner2[0], corner2[1], corner3[0], corner3[1], (1.0,(counter%255)/255,1.0) ))
    
    
    earth = planetobj()
    earth.gplanet(200)
    
    earth.mkplanet(50 ,50)
    print(earth.trias)
    plt.figure()
    plt.scatter( [48,48,52,52],[-50,50,-50,50] )
    for t in earth.trias:
        tri = np.array(t[:6]).reshape(3,2)
        plt.gca().add_patch(plt.Polygon( tri, color=t[6] ))
    plt.show()
    

    Output: enter image description here