Update and rename vanishing_tiles.py to vanishing_tiles.py

This commit is contained in:
Mr.Paradox 2026-06-10 09:18:14 +05:30 committed by GitHub
parent 929ce3f26f
commit e091fb6983
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,10 +1,5 @@
# ba_meta require api 9 # ba_meta require api 9
from __future__ import annotations from __future__ import annotations
from bascenev1lib.gameutils import SharedObjects
import bascenev1 as bs
import babase
import random
from typing import Optional, List, Dict, Any
# Vanishing Tiles - BombSquad Minigame # Vanishing Tiles - BombSquad Minigame
# Tiles disappear one by one. Survive all rounds to win. # Tiles disappear one by one. Survive all rounds to win.
@ -15,12 +10,18 @@ plugman = dict(
description="Tiles disappear gradually. Survive each round to continue. Last player standing wins!", description="Tiles disappear gradually. Survive each round to continue. Last player standing wins!",
external_url="https://discord.gg/sQGDsztQcy", external_url="https://discord.gg/sQGDsztQcy",
authors=[ authors=[
{"name": "Mr.ghosty", "email": "", "discord": "gaurangbroyo"}, {"name": "Mr.Paradox", "email": "microsoftusergame@gmail.com", "discord": "gaurangbroyo"},
{"name": "senchx", "email": "", "discord": "senchx0"}, {"name": "senchx", "email": "", "discord": "senchx0"},
], ],
version="2.0.0", version="1.0.2",
) )
from typing import Optional, List, Dict, Any
import random
import babase
import bascenev1 as bs
from bascenev1lib.gameutils import SharedObjects
class Player(bs.Player['Team']): class Player(bs.Player['Team']):
def __init__(self) -> None: def __init__(self) -> None:
@ -57,19 +58,19 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
def __init__(self, settings: dict) -> None: def __init__(self, settings: dict) -> None:
super().__init__(settings) super().__init__(settings)
self._epic_mode: bool = bool(settings.get('Epic Mode', False)) self._epic_mode = bool(settings.get('Epic Mode', False))
self._show_credits: bool = bool(settings.get('Show Credits', True)) self._show_credits = bool(settings.get('Show Credits', True))
self.default_music = bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SURVIVAL self.default_music = bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SURVIVAL
self._round: int = 1 self._round = 1
self._removing: bool = False self._removing = False
self._game_start_time: Optional[float] = None self._game_start_time: Optional[float] = None
self._tile_nodes: Dict[int, bs.Node] = {} self._tile_nodes: Dict[int, bs.Node] = {}
self._region_nodes: Dict[int, bs.Node] = {} self._region_nodes: Dict[int, bs.Node] = {}
self._present_tile_ids: set[int] = set() self._present_tile_ids: set[int] = set()
self._remove_speed: float = 1.8 self._remove_speed = 1.8
self._collide_mat = bs.Material() self._collide_mat = bs.Material()
self._collide_mat.add_actions(actions=(('modify_part_collision', 'collide', True),)) self._collide_mat.add_actions(actions=(('modify_part_collision', 'collide', True),))
@ -90,12 +91,10 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
def spawn_player(self, player: Player) -> Any: def spawn_player(self, player: Player) -> Any:
if isinstance(self.session, bs.FreeForAllSession): if isinstance(self.session, bs.FreeForAllSession):
pos = VanishingTilesMapDefs.points['spawn1'] spaz = self.spawn_player_spaz(player, position=VanishingTilesMapDefs.points['spawn1'])
spaz = self.spawn_player_spaz(player, position=pos)
else: else:
spaz = self.spawn_player_spaz(player) spaz = self.spawn_player_spaz(player)
spaz.connect_controls_to_player( spaz.connect_controls_to_player(enable_punch=False, enable_pickup=False, enable_bomb=False)
enable_punch=False, enable_pickup=False, enable_bomb=False)
spaz.set_bomb_count(0) spaz.set_bomb_count(0)
return spaz return spaz
@ -105,20 +104,13 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
if self._show_credits: if self._show_credits:
self._credit_node = bs.newnode('text', attrs={ self._credit_node = bs.newnode('text', attrs={
'text': 'Made by Mr.Ghosty', 'text': 'Made by Mr.Paradox & senchx',
'scale': 0.7, 'scale': 0.7, 'position': (0, 8), 'shadow': 0.8, 'flatness': 1.0,
'position': (0, 8), 'color': (1.0, 0.3, 0.8, 1.0), 'h_align': 'center', 'v_attach': 'bottom',
'shadow': 0.8,
'flatness': 1.0,
'color': (1.0, 0.3, 0.8, 1.0),
'h_align': 'center',
'v_attach': 'bottom',
}) })
bs.animate_array(self._credit_node, 'color', 4, { bs.animate_array(self._credit_node, 'color', 4, {
0.0: [1.0, 0.3, 0.8, 1.0], 0.0: [1.0, 0.3, 0.8, 1.0], 1.0: [0.3, 0.8, 1.0, 1.0],
1.0: [0.3, 0.8, 1.0, 1.0], 2.0: [0.4, 1.0, 0.4, 1.0], 3.0: [1.0, 1.0, 0.2, 1.0],
2.0: [0.4, 1.0, 0.4, 1.0],
3.0: [1.0, 1.0, 0.2, 1.0],
4.0: [1.0, 0.3, 0.8, 1.0], 4.0: [1.0, 0.3, 0.8, 1.0],
}, loop=True) }, loop=True)
@ -129,8 +121,8 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
if not isinstance(self.session, bs.FreeForAllSession): if not isinstance(self.session, bs.FreeForAllSession):
if not all(len(t.players) >= 1 for t in self.teams): if not all(len(t.players) >= 1 for t in self.teams):
bs.broadcastmessage('Not enough players draw!', color=(1, 1, 0)) bs.broadcastmessage('Not enough players - draw!', color=(1, 1, 0))
bs.timer(1.0, bs.CallStrict(self.end, bs.GameResults())) bs.timer(1.0, lambda: self.end(bs.GameResults()))
return return
bs.timer(1.0, self._check_initial_state) bs.timer(1.0, self._check_initial_state)
@ -139,33 +131,24 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
def _build_hud(self) -> None: def _build_hud(self) -> None:
for attr in ('_hud_round', '_hud_players', '_hud_tiles'): for attr in ('_hud_round', '_hud_players', '_hud_tiles'):
node = getattr(self, attr, None) node = getattr(self, attr, None)
if node: if node is not None and node.exists():
try:
node.delete() node.delete()
except Exception:
pass
setattr(self, attr, None) setattr(self, attr, None)
self._hud_round = bs.newnode('text', attrs={ self._hud_round = bs.newnode('text', attrs={
'text': '', 'scale': 0.85, 'position': (0, -40), 'text': '', 'scale': 0.85, 'position': (0, -40), 'maxwidth': 300,
'maxwidth': 300, 'h_align': 'center', 'v_align': 'center', 'h_align': 'center', 'v_align': 'center', 'v_attach': 'top', 'h_attach': 'center',
'v_attach': 'top', 'h_attach': 'center', 'shadow': 1.0, 'flatness': 1.0, 'color': (1, 1, 1, 1), 'in_world': False,
'shadow': 1.0, 'flatness': 1.0, 'color': (1, 1, 1, 1),
'in_world': False,
}) })
self._hud_players = bs.newnode('text', attrs={ self._hud_players = bs.newnode('text', attrs={
'text': '', 'scale': 0.8, 'position': (0, -58), 'text': '', 'scale': 0.8, 'position': (0, -58), 'maxwidth': 300,
'maxwidth': 300, 'h_align': 'center', 'v_align': 'center', 'h_align': 'center', 'v_align': 'center', 'v_attach': 'top', 'h_attach': 'center',
'v_attach': 'top', 'h_attach': 'center', 'shadow': 1.0, 'flatness': 1.0, 'color': (1, 0.8, 0.2, 1), 'in_world': False,
'shadow': 1.0, 'flatness': 1.0, 'color': (1, 0.8, 0.2, 1),
'in_world': False,
}) })
self._hud_tiles = bs.newnode('text', attrs={ self._hud_tiles = bs.newnode('text', attrs={
'text': '', 'scale': 0.8, 'position': (0, -74), 'text': '', 'scale': 0.8, 'position': (0, -74), 'maxwidth': 300,
'maxwidth': 300, 'h_align': 'center', 'v_align': 'center', 'h_align': 'center', 'v_align': 'center', 'v_attach': 'top', 'h_attach': 'center',
'v_attach': 'top', 'h_attach': 'center', 'shadow': 1.0, 'flatness': 1.0, 'color': (0.5, 1.0, 0.5, 1), 'in_world': False,
'shadow': 1.0, 'flatness': 1.0, 'color': (0.5, 1.0, 0.5, 1),
'in_world': False,
}) })
self._refresh_hud() self._refresh_hud()
@ -176,37 +159,27 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
if self._hud_round: if self._hud_round:
self._hud_round.text = f'Round {self._round}' self._hud_round.text = f'Round {self._round}'
if self._hud_players: if self._hud_players:
self._hud_players.text = f'Players alive: {alive}' self._hud_players.text = f'Players alive: {alive}'
if self._hud_tiles: if self._hud_tiles:
self._hud_tiles.color = (1.0, 0.3, 0.3, 1) if urgent else (0.5, 1.0, 0.5, 1) self._hud_tiles.color = (1.0, 0.3, 0.3, 1) if urgent else (0.5, 1.0, 0.5, 1)
self._hud_tiles.text = f'Tiles left: {tiles}' self._hud_tiles.text = f'Tiles left: {tiles}'
def _show_round_banner(self) -> None: def _show_round_banner(self) -> None:
node = bs.newnode('text', attrs={ node = bs.newnode('text', attrs={
'text': f'Round {self._round}', 'text': f'Round {self._round}', 'scale': 1.3, 'position': (0, 60),
'scale': 1.3, 'shadow': 1.2, 'flatness': 0.7, 'color': (1, 1, 0, 1),
'position': (0, 60), 'h_align': 'center', 'v_attach': 'center', 'in_world': False,
'shadow': 1.2,
'flatness': 0.7,
'color': (1, 1, 0, 1),
'h_align': 'center',
'v_attach': 'center',
'in_world': False,
}) })
bs.animate(node, 'scale', {0: 0.0, 0.15: 1.3, 2.0: 1.3, 2.5: 0.0}) bs.animate(node, 'scale', {0: 0.0, 0.15: 1.3, 2.0: 1.3, 2.5: 0.0})
bs.timer(2.6, bs.CallStrict(node.delete)) bs.timer(2.6, node.delete)
def on_player_join(self, player: Player) -> None: def on_player_join(self, player: Player) -> None:
if self.has_begun(): if self.has_begun():
player.death_time = bs.time() player.death_time = bs.time()
bs.broadcastmessage( bs.broadcastmessage(
f'{player.getname()} joined! Currently Round {self._round}' f'{player.getname()} joined! Round {self._round} - {len(self._present_tile_ids)} tiles left.',
f'{len(self._present_tile_ids)} tiles left.', color=(0.5, 1.0, 1.0), transient=True,
color=(0.5, 1.0, 1.0),
transient=True,
) )
return return
self.spawn_player(player) self.spawn_player(player)
@ -226,20 +199,13 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
shared = SharedObjects.get() shared = SharedObjects.get()
for i, pos in enumerate(positions): for i, pos in enumerate(positions):
tile = bs.newnode('prop', attrs={ tile = bs.newnode('prop', attrs={
'body': 'puck', 'body': 'puck', 'position': pos, 'mesh': model,
'position': pos, 'mesh_scale': 3.73, 'body_scale': 3.73, 'gravity_scale': 0.0,
'mesh': model, 'color_texture': self._default_tex, 'reflection': 'soft',
'mesh_scale': 3.73,
'body_scale': 3.73,
'gravity_scale': 0.0,
'color_texture': self._default_tex,
'reflection': 'soft',
'materials': [self._no_collide_mat], 'materials': [self._no_collide_mat],
}) })
region = bs.newnode('region', attrs={ region = bs.newnode('region', attrs={
'position': pos, 'position': pos, 'scale': (3.5, 0.1, 3.5), 'type': 'box',
'scale': (3.5, 0.1, 3.5),
'type': 'box',
'materials': [self._collide_mat, shared.footing_material], 'materials': [self._collide_mat, shared.footing_material],
}) })
self._tile_nodes[i] = tile self._tile_nodes[i] = tile
@ -266,7 +232,6 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
for p in self.players: for p in self.players:
if p.is_alive() and p.actor and p.actor.exists(): if p.is_alive() and p.actor and p.actor.exists():
p.actor.node.handlemessage(bs.CelebrateMessage(3.0)) p.actor.node.handlemessage(bs.CelebrateMessage(3.0))
self._refresh_hud() self._refresh_hud()
bs.timer(3.0, self._round_end_check) bs.timer(3.0, self._round_end_check)
@ -275,8 +240,7 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
self._make_final_tile() self._make_final_tile()
return return
urgent = len(self._present_tile_ids) <= 4 if len(self._present_tile_ids) <= 4:
if urgent:
bs.getsound('shieldDown').play(0.4) bs.getsound('shieldDown').play(0.4)
tile_id = random.choice(list(self._present_tile_ids)) tile_id = random.choice(list(self._present_tile_ids))
@ -294,11 +258,8 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
def vanish() -> None: def vanish() -> None:
if tile.exists(): if tile.exists():
bs.emitfx( bs.emitfx(position=tile.position, count=20, scale=0.9,
position=tile.position, spread=0.5, chunk_type='spark')
count=20, scale=0.9, spread=0.5,
chunk_type='spark',
)
tile.delete() tile.delete()
if region and region.exists(): if region and region.exists():
region.delete() region.delete()
@ -311,8 +272,7 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
self.slow_motion = self._epic_mode self.slow_motion = self._epic_mode
if not isinstance(self.session, bs.FreeForAllSession): if not isinstance(self.session, bs.FreeForAllSession):
living_teams = [ living_teams = [t for t in self.teams if any(p.is_alive() for p in t.players)]
t for t in self.teams if any(p.is_alive() for p in t.players)]
if len(living_teams) <= 1: if len(living_teams) <= 1:
self._removing = False self._removing = False
self.end_game() self.end_game()
@ -326,15 +286,12 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
self._remove_speed = max(0.3, self._remove_speed * 0.75) self._remove_speed = max(0.3, self._remove_speed * 0.75)
self._round += 1 self._round += 1
survivors = [p for p in self.players if p.is_alive()] survivors = [p for p in self.players if p.is_alive()]
bs.broadcastmessage( bs.broadcastmessage(f'Round {self._round}! Speed increasing!', color=(0.5, 1.0, 1.0))
f'Round {self._round}! Speed increasing!', color=(0.5, 1.0, 1.0)) bs.timer(1.5, lambda s=survivors: self._next_round(s))
bs.timer(1.5, bs.CallStrict(self._next_round, survivors))
def _next_round(self, survivors: List[Player]) -> None: def _next_round(self, survivors: List[Player]) -> None:
safety = bs.newnode('region', attrs={ safety = bs.newnode('region', attrs={
'position': (0, 1.5, -5), 'position': (0, 1.5, -5), 'scale': (20, 0.2, 20), 'type': 'box',
'scale': (20, 0.2, 20),
'type': 'box',
'materials': [SharedObjects.get().footing_material], 'materials': [SharedObjects.get().footing_material],
}) })
self._cleanup_tiles() self._cleanup_tiles()
@ -344,18 +301,16 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
for p in survivors: for p in survivors:
if p.actor and p.actor.exists(): if p.actor and p.actor.exists():
p.actor.handlemessage( p.actor.handlemessage(bs.StandMessage(VanishingTilesMapDefs.points['spawn1']))
bs.StandMessage(VanishingTilesMapDefs.points['spawn1']))
bs.timer(2.5, bs.CallStrict(safety.delete)) bs.timer(2.5, safety.delete)
self._removing = False self._removing = False
bs.timer(3.0, self._start_removal) bs.timer(3.0, self._start_removal)
def handlemessage(self, msg: Any) -> Any: def handlemessage(self, msg: Any) -> Any:
if isinstance(msg, bs.PlayerDiedMessage): if isinstance(msg, bs.PlayerDiedMessage):
super().handlemessage(msg) super().handlemessage(msg)
p = msg.getplayer(Player) msg.getplayer(Player).death_time = bs.time()
p.death_time = bs.time()
self._refresh_hud() self._refresh_hud()
bs.timer(0.5, self._check_end_game) bs.timer(0.5, self._check_end_game)
return None return None
@ -372,21 +327,18 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
return return
for team in self.teams: for team in self.teams:
if len(team.players) == 0: if len(team.players) == 0:
winner = next((t for t in self.teams if t is not team), None) bs.broadcastmessage('A team has no players - game over!', color=(1, 1, 0))
bs.broadcastmessage('A team has no players — game over!', bs.timer(1.0, self.end_game)
color=(1, 1, 0))
bs.timer(1.0, bs.CallStrict(self.end_game))
return return
def _check_end_game(self) -> None: def _check_end_game(self) -> None:
if not self.has_begun(): if not self.has_begun():
return return
if not isinstance(self.session, bs.FreeForAllSession): if not isinstance(self.session, bs.FreeForAllSession):
if len([t for t in self.teams if len([t for t in self.teams if any(p.is_alive() for p in t.players)]) <= 1:
if any(p.is_alive() for p in t.players)]) <= 1:
self.end_game() self.end_game()
else: else:
if len([p for p in self.players if p.is_alive()]) == 0: if len([p for p in self.players if p.is_alive()]) <= 1:
self.end_game() self.end_game()
def end_game(self) -> None: def end_game(self) -> None:
@ -404,17 +356,11 @@ class VanishingTilesGame(bs.TeamGameActivity[Player, Team]):
for attr in ('_hud_round', '_hud_players', '_hud_tiles'): for attr in ('_hud_round', '_hud_players', '_hud_tiles'):
node = getattr(self, attr, None) node = getattr(self, attr, None)
if node: if node is not None and node.exists():
try:
node.delete() node.delete()
except Exception:
pass
if self._credit_node: if self._credit_node and self._credit_node.exists():
try:
self._credit_node.delete() self._credit_node.delete()
except Exception:
pass
self.end(results=results) self.end(results=results)
@ -448,33 +394,27 @@ class VanishingTilesMap(bs.Map):
@classmethod @classmethod
def on_preload(cls) -> Any: def on_preload(cls) -> Any:
return { return {'bgtex': bs.gettexture('menuBG'), 'bgmesh': bs.getmesh('thePadBG')}
'bgtex': bs.gettexture('menuBG'),
'bgmesh': bs.getmesh('thePadBG'),
}
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
self.node = bs.newnode('terrain', attrs={ self.node = bs.newnode('terrain', attrs={
'mesh': self.preloaddata['bgmesh'], 'mesh': self.preloaddata['bgmesh'], 'lighting': False,
'lighting': False, 'background': True, 'color_texture': self.preloaddata['bgtex'],
'background': True,
'color_texture': self.preloaddata['bgtex'],
}) })
try:
bs.register_map(VanishingTilesMap)
except Exception:
bs._map.register_map(VanishingTilesMap) bs._map.register_map(VanishingTilesMap)
# ba_meta export babase.Plugin # ba_meta export babase.Plugin
class Main(babase.Plugin): class Main(babase.Plugin):
def __init__(self) -> None: def __init__(self) -> None:
babase.app.classic.add_coop_practice_level( babase.app.classic.add_coop_practice_level(bs.Level(
bs.Level( name='Vanishing Tiles', displayname='Vanishing Tiles',
name='Vanishing Tiles', gametype=VanishingTilesGame, settings={},
displayname='Vanishing Tiles',
gametype=VanishingTilesGame,
settings={},
preview_texture_name='powerupHealth', preview_texture_name='powerupHealth',
) ))
)