codetower/ct_lib.py

568 lines
25 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import bge # Blender Game Engine (UPBGE)
import aud # Sounds
import threading # Multithreading
import trace
import sys
import time
import math
import mathutils
import random
###############################################################################
# ct_lib.py
# @title: User library
# @project: CodeTower
# @lang: fr,en
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2022 Philippe Roy
# @license: GNU GPL
#
# Ce simulateur est un jeu du type tower defense où les tours sont à piloter par la programmation Python.
# This game is a tower defense coding game. The towers are driven with Python code.
#
# Commandes déclenchées par les joueurs : ct_*
# Commandes déclenchées par la scene 3D : scn_*
#
###############################################################################
scene = bge.logic.getCurrentScene()
# Colors
tower_purple = [0.202, 0.114, 0.521,1]
tower_turquoise = [0.051, 0.270, 0.279,1]
tower_magenta = [0.799, 0.005, 0.314,1]
tower_orange = [0.799, 0.130, 0.063,1]
tower_yellow = [0.799, 0.617, 0.021, 1]
tower_green = [0.246, 0.687, 0.078, 1]
tower_red = [0.799, 0.031, 0.038, 1]
tower_blue = [0.127, 0.456, 1.000, 1]
ray_yellow = [0.799, 0.617, 0.021, 1] # [0.8, 0.619, 0.021])
ray_blue = [0.127, 0.456, 1.000, 1]
# Sounds
audiodev = aud.Device()
snd_build = aud.Sound('asset/sounds/build.wav')
sndbuff_build = aud.Sound.cache(snd_build)
snd_archer = aud.Sound('asset/sounds/archer.wav')
sndbuff_archer = aud.Sound.cache(snd_archer)
snd_mage = aud.Sound('asset/sounds/mage.wav')
sndbuff_mage = aud.Sound.cache(snd_mage)
snd_life = aud.Sound('asset/sounds/life.ogg')
sndbuff_life = aud.Sound.cache(snd_life)
# handle_buffered = device.play(sound_buffered)
# handle_buffered.stop()
###############################################################################
# Méthode kill pour les tâches (threads)
###############################################################################
class thread_with_trace(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self.__run_backup = self.run
self.run = self.__run
threading.Thread.start(self)
def __run(self):
sys.settrace(self.globaltrace)
self.__run_backup()
self.run = self.__run_backup
def globaltrace(self, frame, event, arg):
if event == 'call':
return self.localtrace
else:
return None
def localtrace(self, frame, event, arg):
if self.killed:
if event == 'line':
raise SystemExit()
return self.localtrace
def kill(self):
self.killed = True
###############################################################################
# Start et stop des tâches (threads)
###############################################################################
def thread_start(threads, type_txt, fct):
threads.append(thread_with_trace(target = fct))
threads[len(threads)-1].start()
print ("Thread",type_txt, "#", len(threads)-1, "open.")
def thread_stop(threads, type_txt):
i=0
zombie_flag=False
for t in threads:
if not t.is_alive():
print ("Thread",type_txt, "#",i,"closed.")
else:
print ("Thread",type_txt, "#",i,"still open ...")
t.kill()
t.join()
if not t.is_alive():
print ("Thread",type_txt, "#",i,"killed.")
else:
print ("Thread",type_txt, "#",i,"zombie...")
zombie_flag=True
i +=1
if zombie_flag==False:
print ("All threads",type_txt, "are closed.")
return True
else:
print ("There are zombies threads",type_txt, ".")
return False
###############################################################################
# Vagues (minions)
###############################################################################
# Minion caracteristics : category (class), level, hp, speed, armor, bounty, lifes_damage
minion_carac={
'Knight-lv1' : ["Knight", 1 , 2.0, 1.0, 0.0, 5,1],
'Knight-lv2' : ["Knight", 2, 4.0, 1.0, 1.0, 20,1],
'Knight-lv3' : ["Knight", 3, 8.0, 1.0, 2.0, 80,1],
'Orc-lv1' : ["Orc", 1 , 2.0, 1.0, 0.0, 5,1],
'Orc-lv2' : ["Orc", 2, 4.0, 1.0, 1.0, 20,1],
'Orc-lv3' : ["Orc", 3, 8.0, 1.0, 2.0, 80,1]}
# Minion 3d object : body (male,female,old, ...), variante (A,B,C,D, ...), level
minion_3d={
'Knight-lv1' : [['Knight_m', 'Knight_f', 'OldKnight_m'],['A','B','C','D'],['common']],
'Knight-lv2' : [['Knight_m', 'Knight_f', 'OldKnight_m'],['A','B','C','D'],['uncommon']],
'Knight-lv3' : [['Knight_m', 'Knight_f', 'OldKnight_m'],['A','B','C','D'],['rare']],
'Orc-lv1' : [['Orc'],['A','B','C','D','E','F'],['common']],
'Orc-lv2' : [['Orc'],['A','B','C','D','E','F'],['uncommon']],
'Orc-lv3' : [['Orc'],['A','B','C','D','E','F'],['rare']]}
# Création d'un minion
def ct_minion(x,y,cat,level):
category=cat+"-lv"+str(level)
body = random.choice(minion_3d[category][0])+"_"+random.choice(minion_3d[category][1])+"_"+random.choice(minion_3d[category][2])
ct_minion_details(x,y,cat,level,body)
# Création d'un minion détaillée
def ct_minion_details(x,y,cat,level,body="Knight_m_A_common"):
category=cat+"-lv"+str(level)
# Pause
while scene.objects['Terrain']['run'] == False:
time.sleep(0.01)
# Object 3D
minion= scene.addObject(body, scene.objects['Terrain'])
minion.worldScale=[0.25,0.25,0.25]
minion.worldPosition=[x,y,0.1]
scene.objects['Terrain']['idm']=scene.objects['Terrain']['idm']+1
minion.name="wm("+str(scene.objects['Terrain']['idm'])+")" # Wave minion (wm), identifier minion (idm)
# minion.worldPosition=mathutils.Vector((x,y,0.3))
# minion.worldPosition=mathutils.Vector((x,y,0.37)) # old 2
scene.objects['Points']['minions'] +=1
scene.objects['Points']['minions_run'] +=1
# print(bge.render.getVsync)
# Caracteristics
minion.components['Minion'].args['cat']=minion_carac[category][0]
minion.components['Minion'].args['level']=minion_carac[category][1]
minion.components['Minion'].args['hp']=minion_carac[category][2]
minion.components['Minion'].args['speed']=minion_carac[category][3]
minion.components['Minion'].args['armor']=minion_carac[category][4]
minion.components['Minion'].args['bounty']=minion_carac[category][5]
minion.components['Minion'].args['lifes_damage']=minion_carac[category][6]
minion['hp'] =minion.components['Minion'].args['hp']
# Actuator Steering
minion.actuators['Steering'].navmesh=scene.objects[scene.objects['Terrain']['navmesh']]
minion.actuators['Steering'].target=scene.objects[scene.objects['Terrain']['endtile']]
minion.actuators['Steering'].distance=0.5
minion.actuators['Steering'].velocity=minion.components['Minion'].args['speed']*scene.objects['Terrain']['speed']
# print (minion.getPropertyNames())
# Destruction d'un minion
def scn_minion_dead(cont):
obj = cont.owner
scene.objects['Points']['minions'] -=1
scene.objects['Points']['minions_run'] -=1
scene.objects['Points']['kills'] +=1
scene.objects['Points']['coins']= scene.objects['Points']['coins']+obj.components['Minion'].args['bounty']
obj.endObject()
###############################################################################
# Tours
###############################################################################
# Tower caracteristics : category (class), damage, speed, range
tower_carac={
'Archer tower' : ["Archer tower", 1.0 , 0.02, 2.5],
'Mage tower' : ["Mage tower", 1.0 , 0.005, 2.5],
'Barrack' : ["Barrack", 1.0 , 0.0001, 2.5]}
tower_minion_3d={
'Archer-lv1' : [['Archer_m', 'Archer_f', "OldArcher_m"],['A','B','C','D'],['common']],
'Archer-lv2' : [['Archer_m', 'Archer_f', "OldArcher_m"],['A','B','C','D'],['uncommon']],
'Archer-lv3' : [['Archer_m', 'Archer_f', "OldArcher_m"],['A','B','C','D'],['rare']],
'Mage-lv1' : [['Mage'],['A','B','C','D'],['common']],
'Mage-lv2' : [['Mage'],['A','B','C','D'],['uncommon']],
'Mage-lv3' : [['Mage'],['A','B','C','D'],['rare']]}
# Création d'une tour
def ct_build(x,y, cat='Archer tower', tower_name="Tower", color=tower_purple, tower_3d="square-A"):
if cat=='Archer tower': # Archer
category="Archer-lv1"
if cat=='Mage tower': # Mage
category="Mage-lv1"
body = random.choice(tower_minion_3d[category][0])+"_"+random.choice(tower_minion_3d[category][1])+"_"+random.choice(tower_minion_3d[category][2])
ct_build_details(x,y, cat, tower_name, color, tower_3d, body)
# Création d'une tour détaillée
def ct_build_details(x,y, cat='Archer tower', tower_name="Tower", color=tower_purple, tower_3d="square-A", body="Archer_m_A_common"):
# Vérification de la place
if [x,y] in scene.objects['Terrain']['scene_tile_noncontruct'] or [x,y] in scene.objects['Terrain']['scene_tile_tower']:
return False
# Vérification du niveau
scene.objects['Points']['level']= scene.objects['Points']['level'] + 1
if scene.objects['Points']['level'] > scene.objects['Points']['level_max'] :
tour= scene.addObject("Tower_error", scene.objects['Terrain'])
tour.worldPosition=[x,y,0.2]
tour.worldScale=[1,1,1]
scene.objects['Terrain']['scene_tile_tower'].append([x,y])
return False
# Objets 3D
tour= scene.addObject('Tower-'+tower_3d, scene.objects['Terrain'])
tour.color = color
tour.worldPosition=[x,y,0.2]
tour.worldScale=[1,1,1]
scene.objects['Terrain']['scene_tile_tower'].append([x,y])
tower_minion= scene.addObject(body, scene.objects['Terrain'])
tower_minion["type_towerminion"]=False
tower_minion.name="tm("+str(x)+','+str(y)+")" # Tower minion (tm)
tower_minion.worldPosition=[x,y,1]
tower_minion.worldScale=[0.25,0.25,0.25]
# Sounds
audiodev.play(sndbuff_build)
# sndhdl_build.stop()
# Caractéristiques (composant python et propriétés de l'objet 3D)
tour.components['Tower'].args['cat']=tower_carac[cat][0]
tour.components['Tower'].args['lvl']=1
tour.components['Tower'].args['tower_name']=tower_name
tour.components['Tower'].args['damage']=tower_carac[cat][1]
tour.components['Tower'].args['speed']=tower_carac[cat][2]
tour.components['Tower'].args['range']=tower_carac[cat][3]
tour['cat']=tower_carac[cat][0]
tour['lvl']=1
tour['tower_name']=tower_name
tour['damage']=tower_carac[cat][1]
tour['speed']=tower_carac[cat][2]
tour['range']=tower_carac[cat][3]
# Gestion du draw
tour['fire_frame']=0
tour['fire_target']=[]
# Capteur Near
tour.sensors['Near'].distance=tour.components['Tower'].args['range']
tour.sensors['Near'].skippedTicks =round(1/(tour.components['Tower'].args['speed']*scene.objects['Terrain']['speed']))
# for obj_i in scene.objects:
# if "type_tower" in obj_i.getPropertyNames():
# print (obj_i['tower_name'])
# print (tour.getPropertyNames())
return True
# Suppression d'une tour
def ct_remove(x,y):
for obj_i in scene.objects:
if "type_tower" in obj_i.getPropertyNames():
if x == obj_i.worldPosition.x and y == obj_i.worldPosition.y:
scene.objects["tm("+str(round(obj_i.worldPosition.x))+','+str(round(obj_i.worldPosition.y))+")"].endObject()
obj_i.endObject()
scene.objects['Points']['level']= scene.objects['Points']['level'] - 1
# Réaction d'une tour
def scn_tower_near(cont):
obj = cont.owner
sensor = obj.sensors['Near']
# Tir
# FIXME: tir sur le plus avancé
if sensor.positive and len(sensor.hitObjectList)>0 and scene.objects['Terrain']['run']==True :
target=sensor.hitObjectList[0]
# target.actuators['Steering'].velocity=(target.components['Minion'].args['speed']*scene.objects['Terrain']['speed'])/2 # Reduction de la vitesse du minion
# Orientation du tower minion
towerminion="tm("+str(round(obj.worldPosition.x))+','+str(round(obj.worldPosition.y))+")"
angle =math.atan((target.worldPosition.y-obj.worldPosition.y)/(target.worldPosition.x-obj.worldPosition.x))
if target.worldPosition.x>obj.worldPosition.x:
angle2=math.pi/2+angle-scene.objects[towerminion].worldOrientation.to_euler().z
angle3=angle
else:
angle2=math.pi+math.pi/2+angle-scene.objects[towerminion].worldOrientation.to_euler().z
angle3=math.pi+angle
scene.objects[towerminion].applyRotation((0, 0, angle2), False)
# Bullet (3d object) (vitesse lente) # -> tendance au plantage
# if scene.objects['Terrain']['speed']<1:
# bullet= scene.addObject("Bullet", scene.objects['Terrain'])
# bullet.mass=0.001 # bullet.applyForce=((0,0,9.81),True)
# bullet.worldPosition=[obj.worldPosition.x,obj.worldPosition.y,1.5]
# bullet.worldScale=[0.75,0.75,0.75]
# # bullet.worldScale=[0.5,0.5,0.5]
# bullet.worldLinearVelocity.x = (target.worldPosition.x-bullet.worldPosition.x)*bullet['velocity']
# bullet.worldLinearVelocity.y= (target.worldPosition.y-bullet.worldPosition.y)*bullet['velocity']
# bullet.worldLinearVelocity.z = (target.worldPosition.z+0.1-bullet.worldPosition.z)*bullet['velocity']
# Ligne (drawLine) (vitesse rapide)
# if scene.objects['Terrain']['speed']>=1:
if scene.objects['Terrain']['speed']<10: # Pas d'animation à 10 -> plantage
# Archer (tir de flêche)
if obj['cat']=="Archer tower":
if target.name in scene.objects:
scene.objects['Terrain']['draw_process']=True
scene.objects['Terrain']['draw_list'].append([5, "arrow", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],target.name, angle3, ray_yellow, 5])
audiodev.play(sndbuff_archer)
# Cast zone
if obj['cat']=="Mage tower": # Mage (cast)
scene.objects['Terrain']['draw_process']=True
scene.objects['Terrain']['draw_list'].append([30, "cast", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],ray_blue,30])
audiodev.play(sndbuff_mage)
# Rayon
if obj['cat']=="Test":
if target.name in scene.objects:
scene.objects['Terrain']['draw_process']=True
scene.objects['Terrain']['draw_list'].append([5, "ray", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8], target.name, angle3, ray_yellow,5]) # Suivi du minion
# Dégats
# FIXME : cast -> buff
target['hp'] = target['hp'] - obj.components['Tower'].args['damage']
if target['hp']<=0:
target['dead']=True
###############################################################################
# Carte
###############################################################################
# Fin
def ct_map_end(x,y):
mapend= scene.addObject("Map_end", scene.objects['Terrain'])
mapend.worldPosition=[x,y,0.2]
mapend.worldScale=[0.25,0.25,0.25]
# Minion arrivé à la fin
def scn_map_end_near(cont):
obj = cont.owner
sensor = obj.sensors['Near']
for i in range (len(sensor.hitObjectList)) :
sensor.hitObjectList[i].endObject()
audiodev.play(sndbuff_life)
if scene.objects['Points']['lifes']>0:
scene.objects['Points']['lifes']= scene.objects['Points']['lifes']-sensor.hitObjectList[0].components['Minion'].args['lifes_damage']
scene.objects['Points']['minions_run'] -=1
# Drapeau de fin
def ct_map_endflag(x,y):
endflag= scene.addObject("Map_endflag", scene.objects['Terrain'])
endflag.worldPosition=[x,y,0.3]
endflag.worldScale=[0.3,0.3,0.3]
if round(x) == x :
if round(y) == y :
scene.objects['Terrain']['scene_tile_noncontruct'].append([x,y])
else:
scene.objects['Terrain']['scene_tile_noncontruct'].append([x,math.floor(y)])
scene.objects['Terrain']['scene_tile_noncontruct'].append([x,math.ceil(y)])
else:
if round(y) == y :
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),y])
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),y])
else:
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),math.floor(y)])
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),math.ceil(y)])
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),math.floor(y)])
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),math.ceil(y)])
###############################################################################
# Temporisation
###############################################################################
def ct_sleep (duration):
time.sleep(duration*(1/scene.objects['Terrain']['speed']))
# def ct_tempo (duration):
# scene.objects['Terrain']['delay_cmd']=0
# while scene.objects['Terrain']['delay_cmd']<duration*(1/scene.objects['Terrain']['speed']):
# # print("Temporization commands :",scene.objects['Terrain']['delay_cmd'])
# time.sleep(0.001)
# # pass
# def ct_tempo_wave (duration):
# scene.objects['Terrain']['delay_wave']=0
# while scene.objects['Terrain']['delay_wave']<duration*(1/scene.objects['Terrain']['speed']):
# # print("Temporization waves :",scene.objects['Terrain']['delay_wave'])
# time.sleep(0.001)
# # pass
# def ct_tempo_wave_trigger (duree):
# print ("delay wave ", scene.objects['Terrain']['delay_wave'])
###############################################################################
# Affichage
###############################################################################
# Texte du panel d'information
def ct_print (text):
# text_info (texte)
if text=="":
scene.objects['Text_info-1'].setVisible(False,False)
scene.objects['Text_info-2'].setVisible(False,False)
else:
lines_txt=texte.split("\n", 6)
for i in range (len(lines_txt),6):
lines_txt.append("")
scene.objects['Text_info-1'].setVisible(True,False)
scene.objects['Text_info-2'].setVisible(True,False)
scene.objects['Text_info-1']['Text']=lines_txt[0]+"\n"+lines_txt[1]+"\n"+lines_txt[2]
scene.objects['Text_info-2']['Text']=lines_txt[3]+"\n"+lines_txt[4]+"\n"+lines_txt[5]
# Texte de carte
def ct_map_text(text):
scene.objects['Map_text']['Text']=text
scene.objects['Map_text'].setVisible(True,False)
###############################################################################
# Dessin bas niveau (bge.render.drawLine)
###############################################################################
def circle (center, radius, color):
ang = 0.0
# ang_step = 0.1
ang_step = 0.2
while ang< 2 * math.pi:
x0 = center[0]+float(radius*math.cos(ang))
y0 = center[1]+float(radius*math.sin(ang))
x1 = center[0]+float(radius*math.cos(ang+ang_step))
y1 = center[1]+float(radius*math.sin(ang+ang_step))
bge.render.drawLine([x0,y0,center[2]],[x1,y1,center[2]],color)
ang += ang_step
# Fire : projectile ou cast
# def scn_tower_fire(cont):
# obj = cont.owner
# if obj["fire_frame"]!=0:
# if obj['cat']=="Archer tower": # Archer (tir de flêche)
# bge.render.drawLine([obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],obj['fire_target'][0], ray_yellow)
# if obj['cat']=="Mage tower": # Mage (cast)
# circle([obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8], 3, ray_blue)
# obj["fire_frame"] -=1
# Affiche les draws en cours
# FIXME: tir sur le plus avancé
#
# Type de draw :
# arrow : [5, "arrow", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],target.name, angle3, ray_yellow,5]
# cast : [30, "cast", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8], ray_blue,30]
# ray : [5, "ray", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],[target.worldPosition.x, target.worldPosition.y, target.worldPosition.z], angle3, ray_yellow,5]
#
def scn_draw(cont):
obj = cont.owner
if obj.sensors['Property'].positive==False:
return
if len(scene.objects['Terrain']['draw_list'])==0:
scene.objects['Terrain']['draw_process']=False
return
# Dépilage des draws à executer
for draw_cmd in scene.objects['Terrain']['draw_list']:
# Archer (tir de flêche)
if draw_cmd[1]=="arrow":
if draw_cmd[3] in scene.objects:
# x0 = draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4]))
# y0 = draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4]))
x0 = draw_cmd[2][0]
y0 = draw_cmd[2][1]
z0 = draw_cmd[2][2]
x1 = scene.objects[draw_cmd[3]].worldPosition.x
y1 = scene.objects[draw_cmd[3]].worldPosition.y
z1 = scene.objects[draw_cmd[3]].worldPosition.z-0.1 # ajustement -0.1
distance = math.sqrt((x1-x0)**2+(y1-y0)**2+(z1-z0)**2)
distance_xy = math.sqrt((x1-x0)**2+(y1-y0)**2)
distance_z = z1-z0
angle_z =math.atan((z1-z0)/(distance_xy))
angle_xy =math.atan((y1-y0)/(x1-x0))
step=distance_xy/(2+draw_cmd[6])
step_z=distance_z/(2+draw_cmd[6])
if x1>x0:
angle2=angle_xy
else:
angle2=math.pi+angle_xy
x2=x0+(((6-draw_cmd[0])*step)*(math.cos(angle2)))
y2=y0+(((6-draw_cmd[0])*step)*(math.sin(angle2)))
z2=z0-(((6-draw_cmd[0])*step_z)*(math.sin(angle_z)))
x3=x0+(((6-draw_cmd[0])*step+step)*(math.cos(angle2)))
y3=y0+(((6-draw_cmd[0])*step+step)*(math.sin(angle2)))
z3=z0-(((6-draw_cmd[0])*step_z+step_z)*(math.sin(angle_z)))
bge.render.drawLine([x2,y2, z2], [x3,y3,z3], draw_cmd[5])
draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
# if scene.objects['Terrain']['speed']<1:
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
# else:
# draw_cmd[0] = draw_cmd[0]-1
# bge.render.drawLine([draw_cmd[2][0]+((6-draw_cmd[0])*0.25)*(math.cos(draw_cmd[4])), draw_cmd[2][1]+((6-draw_cmd[0])*0.25)*(math.sin(draw_cmd[4])),draw_cmd[2][2]],
# [draw_cmd[2][0]+((6-draw_cmd[0])*0.25+0.25)*(math.cos(draw_cmd[4])), draw_cmd[2][1]+((6-draw_cmd[0])*0.25+0.25)*(math.sin(draw_cmd[4])),draw_cmd[2][2]],
# draw_cmd[5])
# Mage (cast)
if draw_cmd[1]=="cast": # Mage (cast)
circle(draw_cmd[2], 3.1-draw_cmd[0]*0.1, draw_cmd[3])
circle(draw_cmd[2], 3-draw_cmd[0]*0.1, draw_cmd[3])
circle(draw_cmd[2], 2.9-draw_cmd[0]*0.1, draw_cmd[3])
draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
# if scene.objects['Terrain']['speed']<=2:
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
# if scene.objects['Terrain']['speed']==4:
# draw_cmd[0] = draw_cmd[0]-draw_cmd[4]/2
# circle(draw_cmd[2], 3, draw_cmd[3]) # simple
# radius=[3,3,2.5,2.5,2,2,1.5,1.5,1,1,1] # basé sur un tableau
# circle(draw_cmd[2], radius[draw_cmd[0]], draw_cmd[3])
# Rayon
if draw_cmd[1]=="ray":
if draw_cmd[3] in scene.objects:
x0 = draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4]))
y0 = draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4]))
x1 = scene.objects[draw_cmd[3]].worldPosition.x
y1 = scene.objects[draw_cmd[3]].worldPosition.y
z1 = scene.objects[draw_cmd[3]].worldPosition.z
bge.render.drawLine([x0,y0, draw_cmd[2][2]], [x1,y1,z1], draw_cmd[5]) # suivi minion
# bge.render.drawLine([draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4])), draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4])), draw_cmd[2][2]], draw_cmd[3], draw_cmd[5]) # décalage minion
# bge.render.drawLine(draw_cmd[2], draw_cmd[3], draw_cmd[5]) # simple
draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
# Suppression des draws finis
i=0
for draw_cmd in scene.objects['Terrain']['draw_list']:
if draw_cmd[0]<=0:
scene.objects['Terrain']['draw_list'].pop(i)
else:
i=i+1
if len(scene.objects['Terrain']['draw_list'])==0:
scene.objects['Terrain']['draw_process']=False