codetower/ct_lib.py

682 lines
28 KiB
Python
Raw Normal View History

2022-03-29 14:12:58 +02:00
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
#
2022-04-01 01:34:54 +02:00
# This game is a tower defense coding game. The towers are driven by Python code.
# Ce simulateur est un jeu du type tower defense où les tours sont à piloter par la programmation Python.
#
2022-03-30 03:10:33 +02:00
# Commands trigged by button : cmd_*
# Commands trigged by 3D scene objects : scn_*
# Commands trigged by user (student or map designer) : ct_*
# 3D scene manipulation : manip_*
#
###############################################################################
scene = bge.logic.getCurrentScene()
2022-03-23 00:27:11 +01:00
# 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)
tower_black = (0, 0, 0, 1)
color_text = (0, 0, 0, 1) # Noir
color_text_red = (0.799, 0.031, 0.038, 1)
color_text_orange = (0.799, 0.176, 0.054, 1)
color_text_yellow = (0.799, 0.617, 0.021, 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)
ray_black = (0, 0, 0, 1)
color_kaykit_black = (0.019, 0.032, 0.037, 1)
2022-03-29 14:12:58 +02:00
# 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)
threads_waves=[]
threads_cmd=[]
2022-03-30 03:10:33 +02:00
###############################################################################
# Données générales
###############################################################################
def ct_level_current():
return scene.objects['Points']['level']
def ct_level():
return scene.objects['Points']['level_max']
2022-03-23 00:27:11 +01:00
###############################################################################
# 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.")
2022-03-29 14:12:58 +02:00
return True
else:
print ("There are zombies threads",type_txt, ".")
2022-03-29 14:12:58 +02:00
return False
def thread_waves_start(fct):
thread_start(threads_waves, "waves", fct)
def thread_waves_stop():
thread_stop(threads_waves, "waves")
def thread_cmd_start(fct):
thread_start(threads_cmd, "commands", fct)
def thread_cmd_stop():
thread_stop(threads_cmd, "commands")
###############################################################################
2022-03-13 05:32:55 +01:00
# Vagues (minions)
###############################################################################
2022-03-23 00:27:11 +01:00
# Minion caracteristics : category (class), level, hp, speed, armor, bounty, lifes_damage
# Minion 3d object : body (male,female,old, ...), variante (A,B,C,D, ...), level
2022-03-13 05:32:55 +01:00
# Création d'un minion
def ct_minion(x,y,cat,level):
category=cat+"-lv"+str(level)
2022-03-30 03:10:33 +02:00
minion_3d= scene.objects['Terrain']['minion_3d']
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)
2022-03-29 14:12:58 +02:00
# 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['id']=scene.objects['Terrain']['idm']
minion.name="wm("+str(minion['id'])+")" # Wave minion (wm), identifier minion (idm)
2022-03-29 14:12:58 +02:00
scene.objects['Points']['minions'] +=1
scene.objects['Points']['minions_run'] +=1
# Gestion de la distance et des minions zombis
minion['dist']=0.0
minion['dist_old']=0.0
minion['dist_last_x']=minion.worldPosition.x
minion['dist_last_y']=minion.worldPosition.y
minion['dist_new']=True
# Caracteristics
2022-03-30 03:10:33 +02:00
minion_carac= scene.objects['Terrain']['minion_carac']
2022-03-31 18:26:55 +02:00
minion['cat']=minion_carac[category][0]
minion['level']=minion_carac[category][1]
minion['hp']=minion_carac[category][2]
minion['speed']=minion_carac[category][3]
minion['speed_base']=minion_carac[category][3]
minion['armor']=minion_carac[category][4]
minion['bounty']=minion_carac[category][5]
minion['lifes_damage']=minion_carac[category][6]
minion['buff']=[]
2022-04-01 01:34:54 +02:00
minion['resist']=[]
# Actuator Steering
2022-03-23 00:27:11 +01:00
minion.actuators['Steering'].navmesh=scene.objects[scene.objects['Terrain']['navmesh']]
minion.actuators['Steering'].target=scene.objects[scene.objects['Terrain']['endtile']]
minion.actuators['Steering'].distance=2
# minion.actuators['Steering'].distance=0.5
2022-03-31 18:26:55 +02:00
minion.actuators['Steering'].velocity=minion['speed_base']*scene.objects['Terrain']['speed']
# Destruction d'un minion
def scn_minion_dead(cont):
obj = cont.owner
2022-03-29 14:12:58 +02:00
scene.objects['Points']['minions'] -=1
scene.objects['Points']['minions_run'] -=1
scene.objects['Points']['kills'] +=1
2022-03-31 18:26:55 +02:00
scene.objects['Points']['coins']= scene.objects['Points']['coins']+obj['bounty']
obj.endObject()
2022-03-13 05:32:55 +01:00
2022-04-01 01:34:54 +02:00
###############################################################################
# Spells / Casts
2022-04-01 01:34:54 +02:00
###############################################################################
# Buff/debuff Minion
def scn_minion_affect(cont):
obj = cont.owner
# print (obj.name, obj['buff'])
slow_state=False
# Distance parcourue
obj['dist']=obj['dist']+ math.sqrt((obj.worldPosition.x-obj['dist_last_x'])**2+(obj.worldPosition.y-obj['dist_last_y'])**2)
obj['dist_last_x']=obj.worldPosition.x
obj['dist_last_y']=obj.worldPosition.y
2022-04-01 01:34:54 +02:00
# Etats actif
for debuff_i in obj['buff']:
if debuff_i[1] <= 0:
obj['buff'].remove(debuff_i)
continue
if debuff_i[0] == "slow":
slow_state=True
debuff_i[1] -= scene.objects['Terrain']['speed']
# Effets
if slow_state:
obj.actuators['Steering'].velocity =(obj['speed_base']*scene.objects['Terrain']['speed'])/3
# obj.actuators['Steering'].velocity =(obj['speed_base']*scene.objects['Terrain']['speed'])/2
2022-04-01 01:34:54 +02:00
else:
obj.actuators['Steering'].velocity = obj['speed_base']*scene.objects['Terrain']['speed']
###############################################################################
# Tours
###############################################################################
2022-03-23 00:27:11 +01:00
# Tower caracteristics : category (class), damage, speed, range
# Création d'une tour
def ct_build(x,y, cat='Archer tower', tower_name="Tower", color=tower_purple, tower_3d="square-A"):
2022-03-30 03:10:33 +02:00
tower_minion_3d= scene.objects['Terrain']['tower_minion_3d']
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)
2022-03-29 14:12:58 +02:00
# 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"):
2022-03-23 00:27:11 +01:00
# 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]
2022-03-23 00:27:11 +01:00
scene.objects['Terrain']['scene_tile_tower'].append([x,y])
return False
# Objets 3D
tour= scene.addObject('Tower-'+tower_3d, scene.objects['Terrain'])
2022-03-23 00:27:11 +01:00
tour.color = color
tour.worldPosition=[x,y,0.2]
tour.worldScale=[1,1,1]
2022-03-23 00:27:11 +01:00
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]
2022-03-29 14:12:58 +02:00
# Sounds
audiodev.play(sndbuff_build)
2022-03-30 03:10:33 +02:00
# Caracteristics
tower_carac= scene.objects['Terrain']['tower_carac']
tour['cat']=tower_carac[cat][0]
2022-03-23 00:27:11 +01:00
tour['tower_name']=tower_name
2022-03-31 18:26:55 +02:00
tour['xp']=0
tour['lvl_current']=1
tour['lvl']=1
tour['damage']=tower_carac[cat][1]
tour['speed']=tower_carac[cat][2]
tour['range']=tower_carac[cat][3]
2022-03-31 18:26:55 +02:00
tour['techno']=[]
2022-04-01 01:34:54 +02:00
tour['cast']="slow"
# tour['cast_duration']=2
tour['cast_duration']=3
tour['target']=[]
tour['target_past']=[]
2022-03-23 00:27:11 +01:00
# Capteur Near
2022-03-31 18:26:55 +02:00
tour.sensors['Near'].distance=tour['range']
tour.sensors['Near'].skippedTicks =round(1/(tour['speed']*scene.objects['Terrain']['speed']))
2022-03-23 00:27:11 +01:00
return True
# Suppression d'une tour
2022-03-23 00:27:11 +01:00
def ct_remove(x,y):
for obj_i in scene.objects:
2022-03-23 00:27:11 +01:00
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()
2022-03-23 00:27:11 +01:00
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
if sensor.positive and len(sensor.hitObjectList)>0 and scene.objects['Terrain']['run']==True :
# Tir sur le plus avancé basé sur les distances parcourues
2022-03-13 05:32:55 +01:00
target=sensor.hitObjectList[0]
target_dist = target['dist']
for obj_i in sensor.hitObjectList:
if obj_i['dist']> target_dist:
target=obj_i
target_dist = target['dist']
# Tir sur le plus avancé basé sur l'ordre de passage
# target=sensor.hitObjectList[0]
# target_id = target['navPosition']
# for obj_i in sensor.hitObjectList:
# if obj_i['navPosition']< target_id:
# target=obj_i
# target_id = target['navPosition']
# Tir sur le plus avancé basé sur les distances par rapport à la tour -> ne marche pas
# target=sensor.hitObjectList[0]
# if len(sensor.hitObjectList)>1:
# target_eloignement = False
# target_distance_eloignement = 0
# target_distance_approche = 100
# print ("detection:",sensor.hitObjectList)
# for obj_i in sensor.hitObjectList:
# for obj_j in obj['target_past']:
# if obj_j[0]==obj_i.name:
# print ("name :", obj_j[0], "distance :", obj.getDistanceTo(obj_i), "distance old :", obj_j[1], "ecart :", obj.getDistanceTo(obj_i) - obj_j[1])
# # Éloignement
# if obj.getDistanceTo(obj_i) - obj_j[1] > 0: # Ecart de distance
# target_eloignement = True
# if obj.getDistanceTo(obj_i) > target_distance_eloignement:
# target=obj_i
# target_distance_eloignement = obj.getDistanceTo(obj_i)
# # Approche
# else:
# if target_eloignement == False:
# if obj.getDistanceTo(obj_i) < target_distance_approche:
# target=obj_i
# target_distance_approche = obj.getDistanceTo(obj_i)
# if target_eloignement == True:
# print ("Eloignement : target:", target.name, "distance :", obj.getDistanceTo(target))
# print ("")
# else:
# print ("Approche : target:", target.name, "distance :", obj.getDistanceTo(target))
# print ("")
# obj['target_past']=[]
# for obj_i in sensor.hitObjectList:
# obj['target_past'].append([obj_i.name, obj.getDistanceTo(obj_i)])
# 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']
2022-03-31 18:26:55 +02:00
# Sounds
if obj['cat']=="Archer tower":
audiodev.play(sndbuff_archer)
if obj['cat']=="Mage tower":
audiodev.play(sndbuff_mage)
# 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
2022-03-30 03:10:33 +02:00
scene.objects['Terrain']['draw_list'].append([5, "arrow", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],target.name, angle3, ray_black, 5])
# 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])
# 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
2022-03-31 18:26:55 +02:00
target['hp'] = target['hp'] - obj['damage']
if target['hp']<=0:
target['dead']=True
2022-04-01 01:34:54 +02:00
# Cast (buff and debuff)
2022-03-30 03:10:33 +02:00
if obj['cat']=="Mage tower":
for target_i in sensor.hitObjectList:
2022-04-01 01:34:54 +02:00
target_i['buff'].append([obj['cast'], obj['cast_duration']])
2022-03-30 03:10:33 +02:00
###############################################################################
# Carte
###############################################################################
2022-03-13 05:32:55 +01:00
# Texte de carte
def ct_map_text_wave(wave):
scene.objects['Map_text']['Text']=("Wave " + str(wave))
scene.objects['Map_text'].setVisible(True,False)
scene.objects['Map_text'].color = color_text_yellow
scene.objects['Map_text']['timer']=120
scene.objects['Map_text']['position_init']=[8.22904, -2.86185, 6.07395]
scene.objects['Map_text']['position_end']=[11.1751, 5.99318, 0.480557]
scene.objects['Map_text'].worldPosition= scene.objects['Map_text']['position_init']
scene.objects['Map_text']['anim']=True
# Texte de carte
def ct_map_text(text):
scene.objects['Map_text']['Text']=text
scene.objects['Map_text'].setVisible(True,False)
# Fin
def ct_map_end(x,y):
scene.objects['Map_end'].worldPosition=[x,y,0.2]
scene.objects['Map_end'].worldScale=[0.25,0.25,0.25]
# Minion arrivé à la fin
def scn_map_end_near(cont):
obj = cont.owner
sensor = obj.sensors['Near']
if sensor.positive :
for obj_i in sensor.hitObjectList :
audiodev.play(sndbuff_life)
if scene.objects['Points']['lifes']>0:
scene.objects['Points']['lifes']= scene.objects['Points']['lifes']-obj_i['lifes_damage']
scene.objects['Points']['minions_run'] -=1
for obj_i in sensor.hitObjectList :
obj_i.endObject()
# def scn_map_end_near(cont):
# obj = cont.owner
# print(obj)
# sensor = obj.sensors['Near']
# if sensor.positive and len(sensor.hitObjectList)>0 :
# # print ("end, len(sensor.hitObjectList) : ", len(sensor.hitObjectList))
# for obj_i in sensor.hitObjectList :
# # print ("obj['idm_last'], obj_i ['id'] : ", obj['idm_last'], obj_i ['id'])
# if obj['idm_last'] != obj_i ['id']:
# obj['idm_last'] = obj_i ['id']
# audiodev.play(sndbuff_life)
# if scene.objects['Points']['lifes']>0:
# scene.objects['Points']['lifes']= scene.objects['Points']['lifes']-obj_i['lifes_damage']
# scene.objects['Points']['minions_run'] -=1
# obj['idm_last'] = obj_i ['id']
# for obj_i in sensor.hitObjectList :
# obj_i.endObject()
# 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 :
2022-03-23 00:27:11 +01:00
scene.objects['Terrain']['scene_tile_noncontruct'].append([x,y])
else:
2022-03-23 00:27:11 +01:00
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 :
2022-03-23 00:27:11 +01:00
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),y])
scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),y])
else:
2022-03-23 00:27:11 +01:00
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'])
2022-03-23 00:27:11 +01:00
###############################################################################
# Affichage
###############################################################################
2022-03-23 00:27:11 +01:00
# Texte du panel d'information
def ct_print (text):
2022-03-23 00:27:11 +01:00
# text_info (texte)
if text=="":
2022-03-23 00:27:11 +01:00
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("")
2022-03-23 00:27:11 +01:00
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]
2022-03-23 00:27:11 +01:00
###############################################################################
# Dessin bas niveau (bge.render.drawLine)
###############################################################################
def circle (center, radius, color):
ang = 0.0
2022-03-29 14:12:58 +02:00
# 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
# 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
2022-03-30 03:10:33 +02:00
if obj.sensors['Draw'].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)
2022-03-30 03:10:33 +02:00
# FIXME : Problème
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