def __init__(self, propelant_anim=None, initial_position_x=0, nave_azul=None, nave_preta=None, nave_amarela=None): self.dead = False self.move_x = 0 self.move_y = 70 self.position_x = initial_position_x self.behavior = self.rand_behavior() self.skin_azul = nave_azul self.skin_amarela = nave_amarela self.skin_preta = nave_preta if self.behavior == "ZigZag": self.rand_zigzag_range = randint(8, 40) self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range self.current_direction = DIRECTION_RIGHT self.elapsed_shoot_time = 0 self.nave_type = randint(0, 2) self.shoot_type_rand = randint(1, 10) if self.shoot_type_rand >= 1 and self.shoot_type_rand <= 5: self.shoot_type = 1 elif self.shoot_type_rand >= 6 and self.shoot_type_rand <= 8: self.shoot_type = 2 else: self.shoot_type = 3 self.propellant = Propellant(propelant_anim, self.position_x, self.move_y + 12, "enemy") self.moving_right = False self.moving_left = False
def load(self, initial_position_x, propellant_anim, nave_azul, nave_amarela, nave_preta): self.dead = False self.move_x = 0 self.move_y = 70 self.position_x = initial_position_x self.skin_azul = nave_azul self.skin_amarela = nave_amarela self.skin_preta = nave_preta self.behavior = self.rand_behavior() if self.behavior == "ZigZag": self.rand_zigzag_range = randint(8, 40) self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range self.current_direction = DIRECTION_RIGHT self.elapsed_shoot_time = 0 self.nave_type = randint(0, 2) self.shoot_type_rand = randint(1, 10) if 1 <= self.shoot_type_rand <= 5: self.shoot_type = 1 elif 6 <= self.shoot_type_rand <= 8: self.shoot_type = 2 else: self.shoot_type = 3 self.propellant = Propellant(propellant_anim, self.position_x, self.move_y + 16.7, "enemy")
def __init__(self, propellant_anim, initial_position): self.dead = False self.move_x = 0 self.moving_left = False self.moving_right = False self.shooting = False self.speed = 0 self.position_x = initial_position self.imageID = self.loadImage() self.propellant = Propellant(propellant_anim, self.position_x, -43.3, "player")
def applyDict(self, dictionary): """Makes the motor copy properties from the dictionary that is passed in, which must be formatted like the result passed out by 'getDict'""" self.nozzle.setProperties(dictionary['nozzle']) if dictionary['propellant'] is not None: self.propellant = Propellant(dictionary['propellant']) else: self.propellant = None self.grains = [] for entry in dictionary['grains']: self.grains.append(grainTypes[entry['type']]()) self.grains[-1].setProperties(entry['properties']) self.config.setProperties(dictionary['config'])
def init_queue(self): for i in range(20): new = Enemy() self.enemy_queue.push(new) for i in range(50): new = Asteroide() self.asteroid_queue.push(new) for i in range(100): new = Shoot() self.bullets_queue.push(new) for i in range(10): new = Planeta() self.planets_queue.push(new) for i in range(50): new = Explode() self.explosion_queue.push(new) for i in range(30): new = Propellant() self.propellant_queue.push(new) for i in range(20): new = Power_up() self.power_queue.push(new)
def init_queue(self): for i in range(10): new = Enemy() self.enemy_queue.push(new) for i in range(10): new = Asteroide() self.asteroid_queue.push(new) for i in range(50): new = Shoot() self.bullets_queue.push(new) for i in range(3): new = Flor() self.flowers_queue.push(new) for i in range(5): new = Planeta() self.planets_queue.push(new) for i in range(21): new = Explode() self.explosion_queue.push(new) for i in range(11): new = Propellant() self.propellant_queue.push(new)
def make_panthera(temperature, of_ratio, ox_tank_volume=None, ox_mass=110): # A test with 30s burn time on White Giant aluminium = Material(2700, 270e6) nitrous_density = nitrous_thermophys(temperature)["rho_l"] ipa_density = ipa_thermophys(temperature)["rho_l"] # Densities multiplied by 0.9 to allow for ullage space if ox_tank_volume == None and (type(ox_mass) == int or type(ox_mass) == float): # We are doing a mass-driven rocket. Mass of propellant is fixed, size is not ox_tank_volume = ox_mass / (nitrous_density * 0.9) fuel_mass = ox_mass * (1 / (1 + of_ratio)) fuel_tank_volume = fuel_mass / (ipa_density * 0.9) elif ox_mass == None and (type(ox_tank_volume) == int or type(ox_tank_volume) == float): # We are doing a volume-driven rocket. Volume of tanks (and thus) height of tanks) is fixed, mass is not fuel_mass = ox_mass * (1 / (1 + of_ratio)) ox_mass = ox_tank_volume * (nitrous_density * 0.9) fuel_tank_volume = fuel_mass / (ipa_density * 0.9) nitrous = Propellant("nitrous-self-pressurised", temperature, ox_tank_volume, ox_mass) ipa = Propellant("ipa-helium-pressurised", temperature, fuel_tank_volume, fuel_mass, nitrous.pressure) # Recommended to have a 20-25% pressure drop across the injector, rounded up to 30% to account for additional plumbing pressure losses # This is equal to a loss of 25% of upstream pressure # Replace this with actual design data at a later date chamber_pressure = nitrous.pressure * 0.5 target_ox_flow = 3.25 target_fuel_flow = target_ox_flow * (1 / (1 + of_ratio)) white_giant = LiquidEngine("ipa-helium-pressurised", "nitrous-self-pressurised", chamber_pressure, target_ox_flow + target_fuel_flow, of_ratio, 4, 0.15) #white_giant.construct_injector(nitrous.pressure, nitrous.temperature, ipa.pressure, ipa.temperature) panthera = Rocket(ipa, nitrous, aluminium, white_giant, 10, 0.15) return (panthera)
class Enemy(): # Inicia os parametros # self.dead = define se o objeto deve ser desenhado # self.move_x = controla o movimento no eixo x # self.move_y = controla o movimento no eixo y, inicia fora da tela (70) # self.position_x = define a posição inical do inimigo # self.beahavior = define o comportamento sobre a movimentação do inimigo # self.skin_* = Texturas pre carregadas # self.ran_zigzag = define o alcance do movimento em zig zag # self.current_direction = indica a direção atual que ele está # self.elapsed_shoot_time = indica o tempo desde o ultimo tiro # self.nave_type = Textura da nave # self.shoot_type_rand = define a quantidade de tiros que o inimigo pode atirar # self.propellant = Objeto "propulsor" da nave def __init__(self, propelant_anim=None, initial_position_x=0, nave_azul=None, nave_preta=None, nave_amarela=None): self.dead = False self.move_x = 0 self.move_y = 70 self.position_x = initial_position_x self.behavior = self.rand_behavior() self.skin_azul = nave_azul self.skin_amarela = nave_amarela self.skin_preta = nave_preta if self.behavior == "ZigZag": self.rand_zigzag_range = randint(8, 40) self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range self.current_direction = DIRECTION_RIGHT self.elapsed_shoot_time = 0 self.nave_type = randint(0, 2) self.shoot_type_rand = randint(1, 10) if self.shoot_type_rand >= 1 and self.shoot_type_rand <= 5: self.shoot_type = 1 elif self.shoot_type_rand >= 6 and self.shoot_type_rand <= 8: self.shoot_type = 2 else: self.shoot_type = 3 self.propellant = Propellant(propelant_anim, self.position_x, self.move_y + 12, "enemy") self.moving_right = False self.moving_left = False # Descreve como o objeto deve ser desenhado def draw(self): # self.propellant.draw() # glColor3f(1.0, 1.0, 1.0) # glDisable(GL_LIGHTING) glEnable(GL_TEXTURE_2D) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) if self.nave_type == 0: glBindTexture(GL_TEXTURE_2D, self.skin_azul) elif self.nave_type == 1: glBindTexture(GL_TEXTURE_2D, self.skin_amarela) elif self.nave_type == 2: glBindTexture(GL_TEXTURE_2D, self.skin_preta) glPushMatrix() # glBegin(GL_QUADS) # glTexCoord2f(0, 1) # glVertex3f(self.move_x + self.position_x -4.0, # self.move_y, 0) # glTexCoord2f(1, 1) # glVertex3f(self.move_x + self.position_x +4.0, # self.move_y, 0) # glTexCoord2f(1, 0) # # glVertex3f(self.move_x + self.position_x + 4.0, # self.move_y + 12, 0) # glTexCoord2f(0, 0) # glVertex3f(self.move_x + self.position_x - 4.0, # self.move_y + 12, 0) # glEnd() if self.moving_right: glRotate(10, 0.1, 0.7, 0.2) elif self.moving_left: glRotate(-10, 0.1, 0.7, 0.2) #Vermelho, baixo glBegin(GL_TRIANGLES) # glColor3f(1.0, 0.0, 0.0) glTexCoord2f(0, 1) glTexCoord2f(1, 1) glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0) glTexCoord2f(1, 0) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0) glTexCoord2f(0, 0) glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0) glEnd() # VERDE esq glBegin(GL_TRIANGLES) # glColor3f(0.0, 1.0, 0.0) glTexCoord2f(0, 1) glTexCoord2f(1, 1) glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0) glTexCoord2f(1, 0) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0) glTexCoord2f(0, 0) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0) glEnd() #############3 Azul escuro dir glBegin(GL_TRIANGLES) # glColor3f(0.5, 0.5, 1.0) glTexCoord2f(0, 1) glTexCoord2f(1, 1) glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0) glTexCoord2f(1, 0) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0) glTexCoord2f(0, 0) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0) glEnd() #####################Roxo FRENTE glBegin(GL_TRIANGLES) # glColor3f(0.0, 0.0, 1.0) glTexCoord2f(0, 1) glTexCoord2f(1, 1) glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0) glTexCoord2f(1, 0) glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0) glTexCoord2f(0, 0) glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0) glEnd() glPopMatrix() glDisable(GL_TEXTURE_2D) # Define como é feito o movimento para a direita da nave def move_right(self): self.move_x += 0.7 self.propellant.move_me(0.7, 0) # Define como é feito o movimento para a esquerda da nave def move_left(self): self.move_x -= 0.7 self.propellant.move_me(-0.7, 0) # Define como é feito o movimento para baixo da nave def move_down(self): self.move_y -= 0.5 self.propellant.move_me(0, -0.5) # Checa se a nave morreu / saiu da tela def check_dead(self): self.check_range() # Define a forma que a nave se move def move_yourself(self): if self.behavior == "Vertical": self.move_down() elif self.behavior == "Diagonal": self.check_max(-49, 49) if self.current_direction == DIRECTION_RIGHT: self.moving_right = True self.moving_left = False self.move_right() self.move_down() elif self.current_direction == DIRECTION_LEFT: self.moving_right = False self.moving_left = True self.move_left() self.move_down() elif self.behavior == "ZigZag": self.check_max(self.zig_x_1, self.zig_x_2) if self.current_direction == DIRECTION_RIGHT: self.moving_right = True self.moving_left = False self.move_right() self.move_down() elif self.current_direction == DIRECTION_LEFT: self.moving_right = False self.moving_left = True self.move_left() self.move_down() # Define a ação a ser feita def act(self): self.move_yourself() # Checa se a nave bateu no alcance minimo ou maximo def check_max(self, min_range, max_range): if self.move_x + self.position_x - 4.0 <= min_range: self.current_direction = DIRECTION_RIGHT elif self.move_x + self.position_x + 4.0 >= max_range: self.current_direction = DIRECTION_LEFT # Checa se a nave está fora da tela def check_range(self): if self.move_y <= -90: self.dead = True self.propellant.im_dead() # Retorna uma tupla do tipo (x1 , x2) def get_x(self): return self.move_x + self.position_x - 5.0, \ self.move_x + self.position_x + 5.0 # Retorna uma tupla do tipo (y1 , y2) def get_y(self): return self.move_y, self.move_y + 12.0 # Retorna uma tupla do tipo (z1 , z2) def get_z(self): return -2, 2 # Retorna um comportamento randomico def rand_behavior(self): choice = randint(0, 91) if choice <= 30: return "Diagonal" elif choice >= 31 and choice <= 60: return "Vertical" elif choice >= 61 and choice <= 90: return "ZigZag" else: return "Daniel" # Carrega os valores do objeto def load(self, initial_position_x, propellant_anim, nave_azul, nave_amarela, nave_preta): self.dead = False self.move_x = 0 self.move_y = 70 self.position_x = initial_position_x self.skin_azul = nave_azul self.skin_amarela = nave_amarela self.skin_preta = nave_preta self.behavior = self.rand_behavior() if self.behavior == "ZigZag": self.rand_zigzag_range = randint(8, 40) self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range self.current_direction = DIRECTION_RIGHT self.elapsed_shoot_time = 0 self.nave_type = randint(0, 2) self.shoot_type_rand = randint(1, 10) if 1 <= self.shoot_type_rand <= 5: self.shoot_type = 1 elif 6 <= self.shoot_type_rand <= 8: self.shoot_type = 2 else: self.shoot_type = 3 self.propellant = Propellant(propellant_anim, self.position_x, self.move_y + 16.7, "enemy") self.moving_right = False self.moving_left = False
class Motor(): """The motor class stores a number of grains, a nozzle instance, a propellant, and a configuration that it uses to run simulations. Simulations return a simRes object that includes any warnings or errors associated with the simulation and the data. The propellant field may be None if the motor has no propellant set, and the grains list is allowed to be empty. The nozzle field and config must be filled, even if they are empty property collections.""" def __init__(self, propDict=None): self.grains = [] self.propellant = None self.nozzle = Nozzle() self.config = MotorConfig() if propDict is not None: self.applyDict(propDict) def getDict(self): """Returns a serializable representation of the motor. The dictionary has keys 'nozzle', 'propellant', 'grains', and 'config', which hold to the properties of their corresponding fields. Grains is a list of dicts, each containing a type and properties. Propellant may be None if the motor has no propellant set.""" motorData = {} motorData['nozzle'] = self.nozzle.getProperties() if self.propellant is not None: motorData['propellant'] = self.propellant.getProperties() else: motorData['propellant'] = None motorData['grains'] = [{ 'type': grain.geomName, 'properties': grain.getProperties() } for grain in self.grains] motorData['config'] = self.config.getProperties() return motorData def applyDict(self, dictionary): """Makes the motor copy properties from the dictionary that is passed in, which must be formatted like the result passed out by 'getDict'""" self.nozzle.setProperties(dictionary['nozzle']) if dictionary['propellant'] is not None: self.propellant = Propellant(dictionary['propellant']) else: self.propellant = None self.grains = [] for entry in dictionary['grains']: self.grains.append(grainTypes[entry['type']]()) self.grains[-1].setProperties(entry['properties']) self.config.setProperties(dictionary['config']) def calcKN(self, regDepth, dThroat): """Returns the motor's Kn when it has each grain has regressed by its value in regDepth, which should be a list with the same number of elements as there are grains in the motor.""" burnoutThres = self.config.getProperty('burnoutWebThres') gWithReg = zip(self.grains, regDepth) perGrain = [ gr.getSurfaceAreaAtRegression(reg) * int(gr.isWebLeft(reg, burnoutThres)) for gr, reg in gWithReg ] surfArea = sum(perGrain) nozz = self.nozzle.getThroatArea(dThroat) return surfArea / nozz def calcIdealPressure(self, regDepth, dThroat, lastPressure, kn=None): """Returns the steady-state pressure of the motor at a given reg. Kn is calculated automatically, but it can optionally be passed in to save time on motors where calculating surface area is expensive.""" density = self.propellant.getProperty('density') ballA, ballN, gamma, temp, molarMass = self.propellant.getCombustionProperties( lastPressure) if kn is None: kn = self.calcKN(regDepth, dThroat) num = kn * density * ballA exponent = 1 / (1 - ballN) denom = ((gamma / ((8314 / molarMass) * temp)) * ((2 / (gamma + 1))**((gamma + 1) / (gamma - 1))))**0.5 return (num / denom)**exponent def calcIdealThrustCoeff(self, chamberPres, dThroat, exitPres=None): """Calculates C_f, the ideal thrust coefficient for the motor's nozzle and propellant, and the given chamber pressure. If nozzle exit presure isn't provided, it will be calculated.""" if chamberPres == 0: return 0 _, _, gamma, _, _ = self.propellant.getCombustionProperties( chamberPres) if exitPres is None: exitPres = self.nozzle.getExitPressure(gamma, chamberPres) ambPres = self.config.getProperty("ambPressure") exitArea = self.nozzle.getExitArea() throatArea = self.nozzle.getThroatArea(dThroat) term1 = (2 * (gamma**2)) / (gamma - 1) term2 = (2 / (gamma + 1))**((gamma + 1) / (gamma - 1)) term3 = 1 - ((exitPres / chamberPres)**((gamma - 1) / gamma)) momentumThrust = (term1 * term2 * term3)**0.5 pressureThrust = ( (exitPres - ambPres) * exitArea) / (throatArea * chamberPres) return momentumThrust + pressureThrust def calcForce(self, chamberPres, dThroat, exitPres=None): """Calculates the force of the motor at a given regression depth per grain. Calculates exit pressure by default, but can also use a value passed in. This method uses a combination of the techniques described in these resources to adjust the thrust coefficient: https://apps.dtic.mil/dtic/tr/fulltext/u2/a099791.pdf and http://rasaero.com/dloads/Departures%20from%20Ideal%20Performance.pdf.""" thrustCoeffIdeal = self.calcIdealThrustCoeff(chamberPres, dThroat, exitPres) divLoss = self.nozzle.getDivergenceLosses() throatLoss = self.nozzle.getThroatLosses(dThroat) skinLoss = self.nozzle.getSkinLosses() efficiency = self.nozzle.getProperty('efficiency') thrustCoeffAdj = divLoss * throatLoss * efficiency * ( skinLoss * thrustCoeffIdeal + (1 - skinLoss)) thrust = thrustCoeffAdj * self.nozzle.getThroatArea( dThroat) * chamberPres return max(thrust, 0) def runSimulation(self, callback=None): """Runs a simulation of the motor and returns a simRes instance with the results. Constraints are checked, including the number of grains, if the motor has a propellant set, and if the grains have geometry errors. If all of these tests are passed, the motor's operation is simulated by calculating Kn, using this value to get pressure, and using pressure to determine thrust and other statistics. The next timestep is then prepared by using the pressure to determine how the motor will regress in the given timestep at the current pressure. This process is repeated and regression tracked until all grains have burned out, when the results and any warnings are returned.""" burnoutWebThres = self.config.getProperty('burnoutWebThres') burnoutThrustThres = self.config.getProperty('burnoutThrustThres') dTime = self.config.getProperty('timestep') simRes = SimulationResult(self) # Check for geometry errors if len(self.grains) == 0: aText = 'Motor must have at least one propellant grain' simRes.addAlert( SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT, aText, 'Motor')) for gid, grain in enumerate(self.grains): if isinstance( grain, EndBurningGrain ) and gid != 0: # Endburners have to be at the foward end aText = 'End burning grains must be the forward-most grain in the motor' simRes.addAlert( SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT, aText, 'Grain ' + str(gid + 1))) for alert in grain.getGeometryErrors(): alert.location = 'Grain ' + str(gid + 1) simRes.addAlert(alert) for alert in self.nozzle.getGeometryErrors(): simRes.addAlert(alert) # Make sure the motor has a propellant set if self.propellant is None: alert = SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT, 'Motor must have a propellant set', 'Motor') simRes.addAlert(alert) else: for alert in self.propellant.getErrors(): simRes.addAlert(alert) # If any errors occurred, stop simulation and return an empty sim with errors if len(simRes.getAlertsByLevel(SimAlertLevel.ERROR)) > 0: print("Error in sim") print(simRes.getAlertsByLevel(SimAlertLevel.ERROR)[0].description) print("in", simRes.getAlertsByLevel(SimAlertLevel.ERROR)[0].location) return simRes # Pull the required numbers from the propellant density = self.propellant.getProperty('density') # Generate coremaps for perforated grains for grain in self.grains: grain.simulationSetup(self.config) # Setup initial values perGrainReg = [0 for grain in self.grains] # At t = 0, the motor has ignited simRes.channels['time'].addData(0) simRes.channels['kn'].addData(self.calcKN(perGrainReg, 0)) igniterPres = self.config.getProperty('igniterPressure') simRes.channels['pressure'].addData( self.calcIdealPressure(perGrainReg, 0, igniterPres, None)) simRes.channels['force'].addData(0) simRes.channels['mass'].addData([ grain.getVolumeAtRegression(0) * density for grain in self.grains ]) simRes.channels['massFlow'].addData([0 for grain in self.grains]) simRes.channels['massFlux'].addData([0 for grain in self.grains]) simRes.channels['regression'].addData([0 for grains in self.grains]) simRes.channels['web'].addData( [grain.getWebLeft(0) for grain in self.grains]) simRes.channels['exitPressure'].addData(0) simRes.channels['dThroat'].addData(0) # Check port/throat ratio and add a warning if it is large enough aftPort = self.grains[-1].getPortArea(0) if aftPort is not None: minAllowed = self.config.getProperty('minPortThroat') ratio = aftPort / geometry.circleArea( self.nozzle.props['throat'].getValue()) if ratio < minAllowed: desc = 'Initial port/throat ratio of ' + str(round( ratio, 3)) + ' was less than ' + str(minAllowed) simRes.addAlert( SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT, desc, 'N/A')) # Perform timesteps while simRes.shouldContinueSim(burnoutThrustThres): # Calculate regression massFlow = 0 perGrainMass = [0 for grain in self.grains] perGrainMassFlow = [0 for grain in self.grains] perGrainMassFlux = [0 for grain in self.grains] perGrainWeb = [0 for grain in self.grains] for gid, grain in enumerate(self.grains): if grain.getWebLeft(perGrainReg[gid]) > burnoutWebThres: # Calculate regression at the current pressure reg = dTime * self.propellant.getBurnRate( simRes.channels['pressure'].getLast()) # Find the mass flux through the grain based on the mass flow fed into from grains above it perGrainMassFlux[gid] = grain.getPeakMassFlux( massFlow, dTime, perGrainReg[gid], reg, density) # Find the mass of the grain after regression perGrainMass[gid] = grain.getVolumeAtRegression( perGrainReg[gid]) * density # Add the change in grain mass to the mass flow massFlow += (simRes.channels['mass'].getLast()[gid] - perGrainMass[gid]) / dTime # Apply the regression perGrainReg[gid] += reg perGrainWeb[gid] = grain.getWebLeft(perGrainReg[gid]) perGrainMassFlow[gid] = massFlow simRes.channels['regression'].addData(perGrainReg[:]) simRes.channels['web'].addData(perGrainWeb) simRes.channels['mass'].addData(perGrainMass) simRes.channels['massFlow'].addData(perGrainMassFlow) simRes.channels['massFlux'].addData(perGrainMassFlux) # Calculate KN dThroat = simRes.channels['dThroat'].getLast() simRes.channels['kn'].addData(self.calcKN(perGrainReg, dThroat)) # Calculate Pressure lastPressure = simRes.channels['pressure'].getLast() lastKn = simRes.channels['kn'].getLast() pressure = self.calcIdealPressure(perGrainReg, dThroat, lastPressure, lastKn) simRes.channels['pressure'].addData(pressure) # Calculate Exit Pressure _, _, gamma, _, _ = self.propellant.getCombustionProperties( pressure) exitPressure = self.nozzle.getExitPressure(gamma, pressure) simRes.channels['exitPressure'].addData(exitPressure) # Calculate force force = self.calcForce(simRes.channels['pressure'].getLast(), dThroat, exitPressure) simRes.channels['force'].addData(force) simRes.channels['time'].addData(simRes.channels['time'].getLast() + dTime) # Calculate any slag deposition or erosion of the throat if pressure == 0: slagRate = 0 else: slagRate = (1 / pressure) * self.nozzle.getProperty('slagCoeff') erosionRate = pressure * self.nozzle.getProperty('erosionCoeff') change = dTime * ((-2 * slagRate) + (2 * erosionRate)) simRes.channels['dThroat'].addData(dThroat + change) if callback is not None: # Uses the grain with the largest percentage of its web left progress = max([ g.getWebLeft(r) / g.getWebLeft(0) for g, r in zip(self.grains, perGrainReg) ]) if callback( 1 - progress ): # If the callback returns true, it is time to cancel return simRes simRes.success = True if simRes.getPeakMassFlux() > self.config.getProperty('maxMassFlux'): desc = 'Peak mass flux exceeded configured limit' alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT, desc, 'Motor') simRes.addAlert(alert) if simRes.getMaxPressure() > self.config.getProperty('maxPressure'): desc = 'Max pressure exceeded configured limit' alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT, desc, 'Motor') simRes.addAlert(alert) # Note that this only adds all errors found on the first datapoint where there were errors to avoid repeating # errors. It should be revisited if getPressureErrors ever returns multiple types of errors for pressure in simRes.channels['pressure'].getData(): if pressure > 0: err = self.propellant.getPressureErrors(pressure) if len(err) > 0: simRes.addAlert(err[0]) break return simRes
class Nave(): # Inicia os parametros # self.dead = indica se o objeto deve ser desenhado # self.move_x = controla o movimento executado pela nave # self.position_x = indica a posição x inicial da nave # self.imageID = variavel para a textura da nave # self.propellant = Objeto "propulsor" da nave def __init__(self, propellant_anim, initial_position): self.dead = False self.move_x = 0 self.moving_left = False self.moving_right = False self.shooting = False self.speed = 0 self.position_x = initial_position self.imageID = self.loadImage() self.propellant = Propellant(propellant_anim, self.position_x, -43.3, "player") # Carrega a imagem da nave do player def loadImage(self, imageName="img/nave2.png"): im = Image.open(imageName) ix, iy, image = im.size[0], im.size[1], im.tobytes() ID = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, ID) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) return ID # Descreve como o objeto deve ser desenhado def draw(self): self.propellant.draw() glColor3f(1.0, 1.0, 1.0) glDisable(GL_LIGHTING) glEnable(GL_TEXTURE_2D) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glBindTexture(GL_TEXTURE_2D, self.imageID) glPushMatrix() glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(self.move_x + self.position_x - 4.0, -40.0, 1) glTexCoord2f(1, 1) glVertex3f(self.move_x + self.position_x + 4.0, -40.0, 1) glTexCoord2f(1, 0) glVertex3f(self.move_x + self.position_x + 4.0, -28.0, 1) glTexCoord2f(0, 0) glVertex3f(self.move_x + self.position_x - 4.0, -28.0, 1) glEnd() glPopMatrix() glDisable(GL_TEXTURE_2D) # Define como é feito o movimento para a direita da nave # e verifica se o movimento pode ser feito def move_right(self): if self.move_x + self.position_x + 4.0 <= 47: self.move_x += 1.5 + self.speed self.propellant.move_me(1.5 + self.speed, 0) # Define como é feito o movimento para a esquerda da nave # e verifica se o movimento pode ser feito def move_left(self): if self.move_x + self.position_x - 4.0 >= -47: self.move_x -= 1.5 + self.speed self.propellant.move_me(-(1.5 + self.speed), 0) def check_dead(self): pass def act(self): if self.moving_left: self.move_left() if self.moving_right: self.move_right() # Retorna uma tupla do tipo (x1 , x2) def get_x(self): return (self.move_x + self.position_x - 4.0, self.move_x + self.position_x + 4.0) # Retorna uma tupla do tipo (y1 , y2) def get_y(self): return (-46.0, -34.0)