Mentions légales du service

Skip to content
Snippets Groups Projects
Commit e1dd9f8a authored by DETROYAT Alexis's avatar DETROYAT Alexis
Browse files

Implemented a multi-sprite handler method in game.py

parent 2e9c167f
No related branches found
No related tags found
3 merge requests!51Improved Holy grail + better objects & characters handling + changed map management,!21Merging the multi-character sprite handling system into avoid_monster,!20Draft: Multi-character sprite management system (same sprite used for various NPCs, each one being independent) + upgraded holy_grail
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.5" orientation="orthogonal" renderorder="right-down" width="14" height="9" tilewidth="32" tileheight="32" infinite="0" backgroundcolor="#000000" nextlayerid="5" nextobjectid="9">
<map version="1.8" tiledversion="1.8.0" orientation="orthogonal" renderorder="right-down" width="14" height="9" tilewidth="32" tileheight="32" infinite="0" backgroundcolor="#000000" nextlayerid="5" nextobjectid="9">
<tileset firstgid="1" source="../../../resources/tiles/[Base]BaseChip_pipo.json"/>
<tileset firstgid="1065" source="../../../resources/tiles/[A]Grass_pipo.json"/>
<tileset firstgid="1593" source="../../../resources/tiles/[A]Water_pipo.json"/>
......@@ -55,12 +55,5 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<objectgroup id="4" name="objects">
<object id="1" name="knight1" gid="156" x="352.176" y="64.9596" width="32" height="32"/>
<object id="2" name="knight2" gid="156" x="352.829" y="96.9466" width="32" height="32"/>
<object id="3" name="knight3" gid="156" x="353.482" y="129.586" width="32" height="32"/>
<object id="4" name="knight4" gid="156" x="352.829" y="193.56" width="32" height="32"/>
<object id="5" name="knight5" gid="156" x="352.176" y="224.894" width="32" height="32"/>
<object id="6" name="knight6" gid="156" x="353.482" y="256.228" width="32" height="32"/>
</objectgroup>
<objectgroup id="4" name="objects"/>
</map>
......@@ -8,7 +8,12 @@ from utils import cus
class Level(AbstractLevel):
def arcade_custom_first_start(self):
knights = [self.map.named_objects[f"knight{i+1}"] for i in range(6)]
knights = [self.map.named_objects[f"knight_{i}"] for i in range(1,7)]
for i in range(6):
if i<3:
knights[i].place_at(11,i+1)
else:
knights[i].place_at(11,i+2)
cus.debug(f"knights objects: {knights}")
def set_knight_position(i):
......@@ -19,6 +24,7 @@ class Level(AbstractLevel):
frames = memory["stack"]
old_x = knight.coord_x
old_y = knight.coord_y
cus.debug(f"Old knight {i+1} coords : {old_x, old_y}")
map = find_map(frames)
if map is not None and map.tiles[0] != None:
......@@ -34,10 +40,12 @@ class Level(AbstractLevel):
count += 1
if knight.coord_x != old_x or knight.coord_y != old_y:
cus.debug(f"New position for {knight}")
cus.debug(f"New position for {knight} : {knight.coord_x, knight.coord_y}")
knight._far_move = 'crowflies'
pl = knight.payload()
pl['action'] = 'hit'
knight.send_update(pl)
knight.send_update(pl) # send "hit" payload
knight.send_update() # send "move" payload
return set_knight_position_internal
......@@ -60,7 +68,7 @@ class Level(AbstractLevel):
pl['action'] = 'hit'
player.send_update(pl)
self.register_breakpoint("knock_back", player_knock_back)
def pre_validation(self):
......
......@@ -4,16 +4,18 @@
* engine_name: input_command
* engine_tags:
* engine_antitags:
*
*
* available_commands: next step edit continue
* interactive: True
*
* OBJknight1: char_rep V
* OBJknight2: char_rep V
* OBJknight3: char_rep V
* OBJknight4: char_rep V
* OBJknight5: char_rep V
* OBJknight6: char_rep V
* characters: knight:6
*
* OBJknight_1: char_rep V
* OBJknight_2: char_rep V
* OBJknight_3: char_rep V
* OBJknight_4: char_rep V
* OBJknight_5: char_rep V
* OBJknight_6: char_rep V
*
* map_height: 9
* map_width: 14
......
......@@ -63,8 +63,9 @@ class GameView(EmptyView):
self.tile_map: arcade.TileMap
self.layers: dict[str, arcade.SpriteList]
self.player: SpPlayer
self.wop: NPC
self.wop = None
self.objects = None # dictionnary for sprite objects
self.character_list = ['guard', 'cook', 'knight'] # list of potential NPC to load
self.has_started = False # whether the inferior has started or not (
self.executing = (
......@@ -595,6 +596,44 @@ class GameView(EmptyView):
return scale
def load_characters(self):
self.wop = spo.SpWop(self.metadata["arcade_skins"]["wop_main"], self.amap)
log.debug(f"created wop {self.wop}")
for char_name in self.character_list:
setattr(self, char_name, None)
if self.metadata['characters']:
log.debug(f"Loading level characters : {self.metadata['characters']}")
for char_name in self.metadata['characters']:
char_number = self.metadata ['characters'][char_name]
if char_number == 1:
sprite_object = spo.SpNPC(self.metadata["arcade_skins"][char_name], self.amap)
setattr(self, char_name, sprite_object)
log.debug(f"created {char_name} : {sprite_object}")
else :
for i in range (1,char_number+1):
sprite_object = spo.SpNPC(self.metadata["arcade_skins"][char_name], self.amap)
setattr(self, f"{char_name}_{i}", sprite_object)
log.debug(f"created {char_name}_{i} : {sprite_object}")
else:
log.debug("No character to load in this level")
def add_characters_to_map(self):
if self.metadata['characters']:
log.debug(f"Adding characters to map : {self.metadata['characters']}")
for char_name in self.metadata['characters']:
char_number = self.metadata['characters'][char_name]
if char_number == 1:
character = getattr(self,char_name)
self.level_maps['main']['tile_map'].sprite_lists['objects'].append(character)
self.level_maps['main']['objects'][char_name] = character
log.debug(f"character {char_name} added to map")
else :
for i in range (1,char_number+1):
character = getattr(self,f"{char_name}_{i}")
self.level_maps['main']['tile_map'].sprite_lists['objects'].append(character)
self.level_maps['main']['objects'][f"{char_name}_{i}"] = character
log.debug(f"character {char_name}_{i} added to map")
def launch_level(self, code_window):
"""
Launch a level already loaded in the window object from a file.
......@@ -618,10 +657,13 @@ class GameView(EmptyView):
self.scale = None # TODO: think what is necessary for scale
# TODO: really need to recreate WOP? Should be the same for all levels
self.wop = spo.SpWop(self.metadata["arcade_skins"]["wop_main"], self.amap)
log.debug(f"created wop {self.wop}")
self.guard = spo.SpNPC(self.metadata["arcade_skins"]["guard"], self.amap)
log.debug(f"created guard {self.guard}")
self.load_characters()
# self.wop = spo.SpWop(self.metadata["arcade_skins"]["wop_main"], self.amap)
# log.debug(f"created wop {self.wop}")
# self.guard = spo.SpNPC(self.metadata["arcade_skins"]["guard"], self.amap)
# log.debug(f"created guard {self.guard}")
# self.knight = spo.SpNPC(self.metadata["arcade_skins"]["knight"], self.amap)
# log.debug(f"created knight {self.knight}")
# Initializing maps
self.load_maps()
......@@ -643,10 +685,16 @@ class GameView(EmptyView):
# TODO: why custom code for guard? Should actually only to that if
# required by the level
# => Need to clean that up and make it more generic
self.guard.far_move = 'crowflies'
if self.guard is not None:
self.guard.far_move = 'crowflies'
if self.knight is not None:
self.knight.far_move = 'pathfind'
# Add guard to list of objects
self.level_maps['main']['tile_map'].sprite_lists['objects'].append(self.guard)
self.level_maps['main']['objects']['guard'] = self.guard
self.add_characters_to_map()
# self.level_maps['main']['tile_map'].sprite_lists['objects'].append(self.guard)
# self.level_maps['main']['objects']['guard'] = self.guard
# self.level_maps['main']['tile_map'].sprite_lists['objects'].append(self.knight)
# self.level_maps['main']['objects']['knight'] = self.knight
# combine objects/coordinates of all maps to pass to the tracker
sp_objs = {'exit': self.exit}
......@@ -710,7 +758,10 @@ class GameView(EmptyView):
# Hide NPCs
# self.guard.visible = False
self.guard.set_reset()
if self.guard is not None:
self.guard.set_reset()
if self.knight is not None:
self.knight.set_reset()
# clear output log
self.output_logbox.reset()
......@@ -994,8 +1045,12 @@ class GameView(EmptyView):
self.amap.change_scale(self.scale)
self.player.rescale(self.scale)
self.wop.rescale(self.scale)
self.guard.rescale(self.scale)
if self.wop:
self.wop.rescale(self.scale)
if self.guard is not None:
self.guard.rescale(self.scale)
if self.knight is not None:
self.knight.rescale(self.scale)
self.exit.rescale(self.scale)
self.breaklight.rescale(self.scale)
......@@ -1035,7 +1090,7 @@ class GameView(EmptyView):
self.breaklight.draw_back()
self.player.draw()
if self.wop.visible:
if self.wop and self.wop.visible:
self.wop.draw()
self.exit.draw_front() # after characters so they can be "inside"
......@@ -1098,7 +1153,8 @@ class GameView(EmptyView):
# Update all regular sprites that are always present
self.player.update()
self.wop.update()
if self.wop:
self.wop.update()
self.exit.update()
self.breaklight.update()
......
......@@ -419,6 +419,7 @@ def extract_metadata(source_file):
# "wop_main": ":characters:Female/Female 19-1.png",
"guard": ":characters:Soldier/Soldier 01-1.png",
# "guard": ":characters:Enemy/Enemy 05-1.png",
"knight": ":characters:Soldier/Soldier 03-1.png"
},
"arcade_sprites": { # this is the old sprite that was used in earlier versions
"exit": (
......@@ -529,6 +530,13 @@ def extract_metadata(source_file):
'hide_commands',
]:
metadata[head] = str_to_list(tail)
elif head == 'characters':
character_dict = {}
for character_info in tail.split():
character_name = character_info.split(":")[0]
character_number = int(character_info.split(":")[1])
character_dict[character_name] = character_number
metadata[head] = character_dict
elif head == 'objects':
# first way of declaring objects: in a list, without any attributes
for objname in str_to_list(tail):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment