codetower/ct_lib.py

256 lines
9.5 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 # 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 <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()
###############################################################################
# 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)