import bge # Bibliothèque Blender Game Engine (UPBGE) import threading # Multithreading import trace import sys import time import math import mathutils import random import ct # Bibliothèque CodeTower ############################################################################### # ct_lib.py # @title: User library # @project: CodeTower # @lang: fr # @authors: Philippe Roy # @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() ############################################################################### # 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.") else: print ("There are zombies threads",type_txt, ".") ############################################################################### # Vagues (minions) # ############################################################################### # Minion category : base, level, hp, speed, armor, bounty, lifes_damage carac_minion={ '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]} # Création d'un minion def ct_minion(x,y,cat,level): # while scene.objects['Terrain']['run'] == False: # Pause # pass # Objet 3D minion= scene.addObject(cat, scene.objects['Terrain']) minion.worldScale=mathutils.Vector((0.25,0.25,0.25)) minion.worldPosition=mathutils.Vector((x,y,0.1)) # minion.worldPosition=mathutils.Vector((x,y,0.3)) # minion.worldPosition=mathutils.Vector((x,y,0.37)) # old 2 scene.objects['Points']['minions']= scene.objects['Points']['minions']+1 # Caractéristiques minion.components['Minion'].args['cat']=carac_minion[cat+"-lv"+str(level)][0] minion.components['Minion'].args['level']=carac_minion[cat+"-lv"+str(level)][1] minion.components['Minion'].args['hp']=carac_minion[cat+"-lv"+str(level)][2] minion.components['Minion'].args['speed']=carac_minion[cat+"-lv"+str(level)][3] minion.components['Minion'].args['armor']=carac_minion[cat+"-lv"+str(level)][4] minion.components['Minion'].args['bounty']=carac_minion[cat+"-lv"+str(level)][5] minion.components['Minion'].args['lifes_damage']=carac_minion[cat+"-lv"+str(level)][6] minion['hp'] =minion.components['Minion'].args['hp'] # Steering minion.actuators['Steering'].navmesh=scene.objects['Navmesh.004'] minion.actuators['Steering'].target=scene.objects['tile_straight.036'] minion.actuators['Steering'].distance=0.5 minion.actuators['Steering'].velocity=2 # minion.actuators['Steering'].velocity=minion.components['Minion'].args['speed'] # Tete # if class_minion=="Knight": # head = random.choice(['Knight_head-A', 'Knight_head-B']) # minion_head= scene.addObject(head, minion) # minion_head.worldScale=mathutils.Vector((0.25,0.25,0.25)) # minion_head.setParent(minion, True, True) # minion_head.localPosition.z=0.703713 # Position de la tête # Accessoires # Destruction d'un minion def scn_minion_dead(cont): obj = cont.owner # if obj['dead']==True: obj.endObject() ############################################################################### # Tours # # Caractéristiques : # - Tour basique : dégats = 1.0 ; portée = 3.0 ; vitesse =0,2, portée = 3.0 # ############################################################################### # Création d'une tour def ct_tower(x,y): # Objet 3D tour= scene.addObject("Tower", scene.objects['Terrain']) tour.worldPosition=mathutils.Vector((x,y,0.2)) tour.worldScale=mathutils.Vector((1,1,1)) scene.objects['Terrain']['scene_non_contruct'].append([x,y]) # Caractéristiques tour.components['Tower'].args['damage']=1.0 tour.components['Tower'].args['speed']=0.2 tour.components['Tower'].args['range']=3.0 # Réaction d'une tour def scn_tower_near(cont): obj = cont.owner sensor = obj.sensors['Near'] if len(sensor.hitObjectList)>0 and scene.objects['Terrain']['run']==True : # Tir target=sensor.hitObjectList[0] target.actuators['Steering'].velocity=target.components['Minion'].args['speed']/2 bullet= scene.addObject("Bullet", scene.objects['Terrain']) bullet.mass=0.001 # bullet.applyForce=((0,0,9.81),True) bullet.worldPosition=mathutils.Vector((obj.worldPosition.x,obj.worldPosition.y,1.5)) 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'] # Dégats target['hp'] = target['hp'] - obj.components['Tower'].args['damage'] if target['hp']<=0: target['dead']=True scene.objects['Points']['minions']= scene.objects['Points']['minions']-1 scene.objects['Points']['coins']= scene.objects['Points']['coins']+target.components['Minion'].args['bounty'] ############################################################################### # 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'] if len(sensor.hitObjectList)>0: print (sensor.hitObjectList) for i in range (len(sensor.hitObjectList)) : sensor.hitObjectList[i].endObject() scene.objects['Points']['lifes']= scene.objects['Points']['lifes']-sensor.hitObjectList[0].components['Minion'].args['lifes_damage'] scene.objects['Points']['minions']= scene.objects['Points']['minions']-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 : print (x,y) scene.objects['Terrain']['scene_non_contruct'].append([x,y]) else: scene.objects['Terrain']['scene_non_contruct'].append([x,math.floor(y)]) scene.objects['Terrain']['scene_non_contruct'].append([x,math.ceil(y)]) else: if round(y) == y : scene.objects['Terrain']['scene_non_contruct'].append([math.floor(x),y]) scene.objects['Terrain']['scene_non_contruct'].append([math.ceil(x),y]) else: scene.objects['Terrain']['scene_non_contruct'].append([math.floor(x),math.floor(y)]) scene.objects['Terrain']['scene_non_contruct'].append([math.floor(x),math.ceil(y)]) scene.objects['Terrain']['scene_non_contruct'].append([math.ceil(x),math.floor(y)]) scene.objects['Terrain']['scene_non_contruct'].append([math.ceil(x),math.ceil(y)]) # Texte de carte def ct_map_text(text): scene.objects['Map_text']['Text']=text scene.objects['Map_text'].setVisible(True,False) ############################################################################### # Temporisation ############################################################################### def tempo (duree): time.sleep(duree)