ajout du paysage

This commit is contained in:
Philippe Roy 2022-03-31 18:26:55 +02:00
commit f9f0977e78
9 changed files with 243 additions and 51 deletions

View File

@ -22,6 +22,8 @@
* Healer -> ciblage
* Régénération des squelettes -> ciblage sur squelette nécromencien
* Barracks
* Plus de XP, d'écu
* Couts moins chère en XP et en écu
### Idées pour les tours d'archer
* Minion avec armure -> augmenter le niveau d'une tour
@ -31,7 +33,7 @@
* Minion qui se régénère -> feu ou acide
* Evaluer le niveau d'une tour (cadence, distance et dégats) -> rédéfinir les paramètres en gardant le même niveau
* Passer mode tir multiple -> moins de dégats mais plus massif
* Tir handicapant (vitesse ou attaque)
* Tir précis handicapant cadence plus faible mais buff de vitesse d'avance/d'attaque
### Idées pour les tours de mage
* Minion trop rapide -> réduire la vitesse des minions tour de magie
@ -40,6 +42,7 @@
* Tour de magie en support -> augmente la cadence et la distance sur une tour précise et proche
* Cast d'aveuglement -> modification du steering
* Cast d'allongement des effets sur une tour de magie précise et proche
* Orienter le cast sur des minions précis
* Evaluer le niveau d'une tour (cadence, distance et nombre de minion, durée du buff) -> rédéfinir les paramètres en gardant le même niveau
* Perte de level, ou redéfinir stratégie -> détruire des tours

Binary file not shown.

BIN
codetower-17.blend Normal file

Binary file not shown.

47
ct.py
View File

@ -105,7 +105,7 @@ def cmd_tower_construct(cont):
scene.objects['Tower_construc_mode'].setVisible(True,False)
scene.objects['Tower_construc_mode'].color = color_cmd
text_info ("Tower position : ")
###############################################################################
# User interface : texte info et compteurs
###############################################################################
@ -143,16 +143,38 @@ def points_maj (cont):
if scene.objects['Level_text'].color == color_text_red and scene.objects['Points']['level'] <= scene.objects['Points']['level_max']:
scene.objects['Level_text'].color = color_text
# Ramasse minions perdues
if scene.objects['Points']['tics']%120 ==0: # Toutes les 2 secondes
scene.objects['Points']['minions_lost']=[]
for obj_i in scene.objects:
if "type_minion" in obj_i.getPropertyNames() and "type_towerminion" not in obj_i.getPropertyNames():
if obj_i.worldLinearVelocity.x >0 and abs(obj_i.worldLinearVelocity.x) < 0.001 and obj_i.worldLinearVelocity.y >0 and abs(obj_i.worldLinearVelocity.y) < 0.001:
print ("Minion lost : x' or y' very slow (x, y, z, x', y') : ", obj_i.name, obj_i.worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z, abs(obj_i.worldLinearVelocity.x), abs(obj_i.worldLinearVelocity.y))
obj_i['dead']=True
elif obj_i.worldPosition.x<scene.objects['Terrain']['size'][0] or obj_i.worldPosition.x>scene.objects['Terrain']['size'][1] or obj_i.worldPosition.y<scene.objects['Terrain']['size'][2] or obj_i.worldPosition.y>scene.objects['Terrain']['size'][3]:
print ("Minion lost : x or y outside the map (x, y, z, x', y') : ", obj_i.name, obj_i.worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z, abs(obj_i.worldLinearVelocity.x), abs(obj_i.worldLinearVelocity.y))
obj_i['dead']=True
# scene.objects['Points']['minions_state'].append([obj_i.name, worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z])
# if scene.objects['Points']['tics']%240 ==0:
# for obj_i in scene.objects:
# if "type_minion" in obj_i.getPropertyNames() and "type_towerminion" not in obj_i.getPropertyNames():
# if obj_i.name
# print (obj_i.name, obj_i.worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z)
# scene.objects['Points']['minions_state'].append([obj_i.name, worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z])
# Fin de la vague
if scene.objects['Terrain']['thread_wave']==False and scene.objects['Terrain']['map_run'] == True :
if scene.objects['Points']['minions_run']==0 :
# Vague suivante
if scene.objects['Points']['wave'] < scene.objects['Terrain']['nb_waves']:
# Fin ou vague suivante
if scene.objects['Points']['lifes'] == 0 or scene.objects['Points']['wave'] == scene.objects['Terrain']['nb_waves'] :
terrain_end ()
else:
scene.objects['Points']['wave'] +=1
ct_map.start(scene.objects['Points']['wave']) # Lancement du script de la vague
else: # Fin de la map
terrain_end ()
###############################################################################
# Terrain
@ -192,7 +214,7 @@ def scn_terrain_mo (cont):
# Initialisation lors du chargement du terrain
def terrain_init (cont):
# Cacher la bannière de fin
scene.objects['End'].setVisible(False,True)
scene.objects['End']['timer']=0
@ -201,8 +223,11 @@ def terrain_init (cont):
scene.objects['Terrain']['draw_process']=False
scene.objects['Terrain']['draw_list']=[]
# Ramasse-miettes
scene.objects['Points']['minions_lost']=[]
# Configuration du moteur de rendu
if scene.objects['Terrain']['speed']<10:
if scene.objects['Terrain']['speed']<4: # smaa avec en vitesse 4 et 10 -> tendance au plantage
eevee.use_eevee_smaa = True
else:
eevee.use_eevee_smaa = False
@ -275,7 +300,7 @@ def terrain_run ():
else:
for obj_i in scene.objects: # Relance des Steerings
if "type_minion" in obj_i.getPropertyNames() and "type_towerminion" not in obj_i.getPropertyNames():
obj_i.actuators['Steering'].velocity=obj_i.components['Minion'].args['speed']*scene.objects['Terrain']['speed']
obj_i.actuators['Steering'].velocity=obj_i['speed_base']*scene.objects['Terrain']['speed']
# Arrêt et réinitialisation du cycle
def terrain_stop ():
@ -361,12 +386,12 @@ def terrain_speed (obj):
# Maj des Nears (Towers) et des Steerings (Minions)
for obj_i in scene.objects:
if "type_tower" in obj_i.getPropertyNames() and "Near" in obj_i.sensors :
obj_i.sensors['Near'].skippedTicks =round(1/(obj_i.components['Tower'].args['speed']*scene.objects['Terrain']['speed']))
obj_i.sensors['Near'].skippedTicks =round(1/(obj_i['speed']*scene.objects['Terrain']['speed']))
if "type_minion" in obj_i.getPropertyNames() and "type_towerminion" not in obj_i.getPropertyNames():
obj_i.actuators['Steering'].velocity=obj_i.components['Minion'].args['speed']*scene.objects['Terrain']['speed']
obj_i.actuators['Steering'].velocity=obj_i['speed_base']*scene.objects['Terrain']['speed']
# Configuration du moteur de rendu
if scene.objects['Terrain']['speed']<4:
if scene.objects['Terrain']['speed']<4: # smaa avec en vitesse 4 et 10 -> tendance au plantage
eevee.use_eevee_smaa = True
else:
eevee.use_eevee_smaa = False

View File

@ -48,7 +48,7 @@ def end():
# En: Tower commands
# Fr: Commandes des tours
#
# Build a tower : ct_build(x, y, category, name, color,style)
# Build a tower : ct_build (x, y, category, name, color, style)
# - x position (integer)
# - y position (integer)
# - category (string) : "Archer tower", "Mage tower" or "Barrack" (not implemented)
@ -61,11 +61,11 @@ def end():
#
# - exemple : ct_build("archer tower", 4,5, "Tower #1",yellow,"round-A")
#
# Remove a tower : ct_remove(x, y)
# Remove a tower : ct_remove (x, y)
# - x position (integer)
# - y position (integer)
#
# Time management (temporization) : ct_tempo(delay)
# Time management (temporization) : ct_sleep (delay)
# - delay : delay in seconds (float)
#
###############################################################################
@ -81,9 +81,9 @@ def commands():
if ct_level()==2:
ct_build(4,-2, "Archer tower", "Tower #2", blue, "square-A")
if ct_level()==3:
ct_build(5,6, "Mage tower", "Tower #3", yellow, "square-A")
ct_build(5,6, "Mage tower", "Tower #3", yellow, "round-A")
end() # End of cycle << DONT CHANGE THIS LINE >>

View File

@ -167,20 +167,32 @@ def ct_minion_details(x,y,cat,level,body="Knight_m_A_common"):
# Caracteristics
minion_carac= scene.objects['Terrain']['minion_carac']
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']
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']=[]
minion['debuff']=[]
# 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']
minion.actuators['Steering'].velocity=minion['speed_base']*scene.objects['Terrain']['speed']
def scn_minion_lost(cont):
obj = cont.owner
print (obj.name, obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z)
# for obj_i in scene.objects:
# if "type_minion" in obj_i.getPropertyNames() and "type_towerminion" not in obj_i.getPropertyNames():
# if obj_i.worldPosition.y>11:
# obj_i.endObject()
# # print (obj_i.name, obj_i.worldPosition.x, obj_i.worldPosition.y, obj_i.worldPosition.z)
# Destruction d'un minion
def scn_minion_dead(cont):
@ -188,7 +200,7 @@ def scn_minion_dead(cont):
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']
scene.objects['Points']['coins']= scene.objects['Points']['coins']+obj['bounty']
obj.endObject()
###############################################################################
@ -240,26 +252,24 @@ def ct_build_details(x,y, cat='Archer tower', tower_name="Tower", color=tower_pu
# Caracteristics
tower_carac= scene.objects['Terrain']['tower_carac']
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['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]
tour['techno']=[]
tour['cast']=""
# 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']))
tour.sensors['Near'].distance=tour['range']
tour.sensors['Near'].skippedTicks =round(1/(tour['speed']*scene.objects['Terrain']['speed']))
# for obj_i in scene.objects:
# if "type_tower" in obj_i.getPropertyNames():
@ -308,22 +318,26 @@ def scn_tower_near(cont):
# bullet.worldLinearVelocity.y= (target.worldPosition.y-bullet.worldPosition.y)*bullet['velocity']
# bullet.worldLinearVelocity.z = (target.worldPosition.z+0.1-bullet.worldPosition.z)*bullet['velocity']
# 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']<11: # Pas d'animation à 10 -> plantage
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_black, 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":
@ -332,19 +346,17 @@ def scn_tower_near(cont):
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
target['hp'] = target['hp'] - obj.components['Tower'].args['damage']
target['hp'] = target['hp'] - obj['damage']
if target['hp']<=0:
target['dead']=True
# Buf
if obj['cat']=="Mage tower":
print (sensor.hitObjectList)
i =0
for target_i in sensor.hitObjectList:
if target.actuators['Steering'].velocity== target.components['Minion'].args['speed']*scene.objects['Terrain']['speed']:
target.actuators['Steering'].velocity /= 2
if target_i.actuators['Steering'].velocity== target['speed_base']*scene.objects['Terrain']['speed']:
target_i.actuators['Steering'].velocity /= 2
i+=1
print (i)
###############################################################################
# Carte
@ -364,7 +376,7 @@ def scn_map_end_near(cont):
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']['lifes']= scene.objects['Points']['lifes']-sensor.hitObjectList[0]['lifes_damage']
scene.objects['Points']['minions_run'] -=1
# Drapeau de fin

49
ct_map.py Normal file
View File

@ -0,0 +1,49 @@
import bge # Bibliothèque Blender Game Engine (UPBGE)
from ct_lib import * # Bibliothèque CodeTower
###############################################################################
# ct_map.py
# @title: Map definition
# @project: CodeTower
# @lang: fr,en
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2022 Philippe Roy
# @license: GNU GPL
#
# This game is a tower defense coding game. The towers are driven with Python code.
#
# The file is the the waves definition
#
###############################################################################
scene = bge.logic.getCurrentScene()
###############################################################################
# Carte 1
###############################################################################
# Loading the map
def map1_init():
# Taille de la carte
scene.objects['Terrain']['taille'] = [-15,15,-10,10]
# Navmesh
scene.objects['Terrain']['navmesh'] = "Navmesh.004"
# Ajout des sorties
scene.objects['Terrain']['endtile'] = "tile_straight.036"
ct_map_end(1,-10)
ct_map_endflag(0.5,-10)
ct_map_endflag(1.5,-10)
# Reset counters
def map1_reset():
scene.objects['Points']['lifes']=10
scene.objects['Points']['lifes_max']=10
scene.objects['Points']['coins']=0
scene.objects['Points']['level']=0
scene.objects['Points']['level_max']=1
scene.objects['Points']['minions']=0
scene.objects['Points']['minions_run']=0

View File

@ -122,7 +122,7 @@ def minion_definition():
def wave1():
ct_map_text("Wave 1")
for i in range (15):
ct_minion(14,3,"Orc",1)
ct_minion_details(14,3,"Orc",1, "Orc_A_common")
ct_sleep (2)
end()
@ -130,16 +130,16 @@ def wave1():
def wave2():
ct_map_text("Wave 2")
for i in range (20):
ct_minion(14,3,"Orc",1)
ct_minion_details(14,3,"Orc",1, "Orc_A_common")
ct_sleep (1)
end()
# Wave 3
def wave3():
ct_map_text("Wave 3")
for i in range (25):
ct_minion(14,3,"Knight",1)
# ct_minion_details(14,3,"Knight",1, "OldKnight_m_A_common")
for i in range (30):
ct_minion_details(14,3,"Orc",1, "Orc_A_common")
# ct_minion(14,3,"Knight",1)
ct_sleep (1)
end()

103
ct_waves.py Normal file
View File

@ -0,0 +1,103 @@
import bge # Bibliothèque Blender Game Engine (UPBGE)
from ct_lib import * # Bibliothèque CodeTower
###############################################################################
# ct_waves.py
# @title: Waves for the CodeTower game
# @project: CodeTower
# @lang: fr,en
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2022 Philippe Roy
# @license: GNU GPL
#
# This game is a tower defense coding game. The towers are driven with Python code.
#
# The file is the the waves definition
#
###############################################################################
###############################################################################
# En: Threads management << DONT CHANGE THIS SECTION >>
# Fr: Gestion des tâches (threads) << NE PAS MODIFIER CETTE SECTION >>
###############################################################################
threads=[]
scene = bge.logic.getCurrentScene()
def start():
scene.objects['Terrain']['thread_wave']=True
thread_start(threads, "waves", waves)
def stop():
if thread_stop(threads, "waves"):
if len(threads)==1:
threads.pop()
###############################################################################
# En: Waves commands
# Fr: Commandes des vagues
#
# Spawn a minion : ct_minion (x, y, cat, level)
# - x spwan position (integer)
# - y spwan position (integer)
# - cat : minion class (string) :
# - Knight
# - Barbarian
# - Warrior
# - Mage
# - Rogue
# - Orc
# - Squelette
# - level (1, 2 or 3)
#
# Time management (temporization) : ct_tempo(delay)
# - delay : delay in seconds (integer)
#
# UI management : ct_map_text(text)
# - text for the wave label
#
#
###############################################################################
# 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={
# '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']]}
def waves():
# Wave 1
scene.objects['Points']['wave']= 1
ct_map_text("Wave 1")
for i in range (15):
ct_minion(14,3,"Orc",1)
ct_sleep (1)
# ct_sleep (20)
# Wave 2
# scene.objects['Points']['wave']= 2
# ct_map_text("Wave 2")
# for i in range (20):
# # ct_minion(14,3,"Knight",1)
# # ct_minion(14,3,"Orc",1)
# ct_minion_details(14,3,"Knight",1, "OldKnight_m_A_common")
# ct_sleep (1)
ct_sleep (2)
print ("Threads waves #", len(threads)-1, "are arrived -> close them.") # Thread closed << DONT CHANGE THIS LINE >>
threads.pop()
scene.objects['Terrain']['thread_wave']=False # End of cycle << DONT CHANGE THIS LINE >>