|
| 1 | +""" |
| 2 | +Space Battle Arena is a Programming Game. |
| 3 | +
|
| 4 | +Copyright (C) 2012-2016 Michael A. Hawker and Brett Wortzman |
| 5 | +
|
| 6 | +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. |
| 7 | +
|
| 8 | +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 9 | +
|
| 10 | +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 11 | +
|
| 12 | +The full text of the license is available online: http://opensource.org/licenses/GPL-2.0 |
| 13 | +""" |
| 14 | + |
| 15 | +from BaubleGame import * |
| 16 | +from Utils import CallbackTimer |
| 17 | +from World.Entities import Entity, PhysicalRound |
| 18 | +from World.WorldEntities import Ship |
| 19 | +from GUI.ObjWrappers.GUIEntity import GUIEntity, wrapcircle |
| 20 | +from World.WorldMath import intpos, friendly_type, PlayerStat, aligninstances, getPositionAwayFromOtherObjects |
| 21 | +from GUI.GraphicsCache import Cache |
| 22 | +from GUI.Helpers import debugfont |
| 23 | +from ThreadStuff.ThreadSafe import ThreadSafeDict |
| 24 | +import logging |
| 25 | +import pygame |
| 26 | +import random |
| 27 | +import thread |
| 28 | +import math |
| 29 | +from operator import attrgetter |
| 30 | + |
| 31 | +class TheHungerBaublesGame(BaseBaubleGame): |
| 32 | + def __init__(self, cfgobj): |
| 33 | + |
| 34 | + self._respawn = cfgobj.getboolean("TheHungerBaubles", "respawn_bauble_on_collect") |
| 35 | + self.__maxcarry = cfgobj.getint("TheHungerBaubles", "ship_cargo_size") |
| 36 | + self.__cornucopia_position = (0, 0) |
| 37 | + self.__cornucopia_radius = cfgobj.getint("TheHungerBaubles", "cornucopia_radius") |
| 38 | + self.__spawned_num = 0 |
| 39 | + |
| 40 | + super(TheHungerBaublesGame, self).__init__(cfgobj) |
| 41 | + |
| 42 | + def game_get_info(self): |
| 43 | + return {"GAMENAME": "TheHungerBaubles"} |
| 44 | + |
| 45 | + def player_added(self, player, reason): |
| 46 | + super(TheHungerBaublesGame, self).player_added(player, reason) |
| 47 | + player.carrying = [] |
| 48 | + player.collected = 0 |
| 49 | + |
| 50 | + def player_get_start_position(self): |
| 51 | + if self.cfg.getboolean("Tournament", "tournament"): |
| 52 | + div = 360 / (len(self._players) / self.cfg.getint("Tournament", "groups")) |
| 53 | + else: |
| 54 | + div = 200 |
| 55 | + |
| 56 | + ang = div * self.__spawned_num |
| 57 | + self.__spawned_num += 1 |
| 58 | + dist = self.__cornucopia_radius + 64 |
| 59 | + return (min(max(32, self.__cornucopia_position[0] + math.cos(math.radians(ang)) * dist), self.world.width - 32), |
| 60 | + min(max(32, self.__cornucopia_position[1] + math.sin(math.radians(ang)) * dist), self.world.height - 32)) |
| 61 | + |
| 62 | + def world_add_remove_object(self, wobj, added): |
| 63 | + # Check if this is a high-value bauble to add to our list of ones to pass to the client |
| 64 | + |
| 65 | + # TODO: If an Asteroid or Dragon is destroyed, deposit bauble |
| 66 | + |
| 67 | + return super(TheHungerBaublesGame, self).world_add_remove_object(wobj, added) |
| 68 | + |
| 69 | + def world_physics_pre_collision(self, obj1, obj2): |
| 70 | + ship, other = aligninstances(obj1, obj2, Ship, Entity) |
| 71 | + |
| 72 | + if ship != None: |
| 73 | + #if isinstance(other, Outpost): |
| 74 | + # logging.info("Ship #%d hit their base", ship.id) |
| 75 | + # return [ False, [self.depositBaubles, ship, other] ] |
| 76 | + if isinstance(other, Bauble): |
| 77 | + return [ False, [self.collectBaubles, ship, other] ] |
| 78 | + |
| 79 | + return super(TheHungerBaublesGame, self).world_physics_pre_collision(obj1, obj2) |
| 80 | + |
| 81 | + def get_player_cargo_value(self, player): |
| 82 | + return sum(b.value for b in player.carrying) |
| 83 | + |
| 84 | + def get_player_cargo_weight(self, player): |
| 85 | + return sum(b.weight for b in player.carrying) |
| 86 | + |
| 87 | + def collectBaubles(self, ship, bauble): |
| 88 | + logging.info("Collected Baubles Ship #%d", ship.id) |
| 89 | + if self.get_player_cargo_weight(ship.player) + bauble.weight <= self.__maxcarry: |
| 90 | + ship.player.carrying.append(bauble) |
| 91 | + ship.player.collected += 1 |
| 92 | + ship.player.update_score(bauble.value) |
| 93 | + ship.player.sound = "BAUBLE" |
| 94 | + |
| 95 | + bauble.destroyed = True |
| 96 | + |
| 97 | + if self._respawn: |
| 98 | + Bauble.spawn(self.world, self.cfg) |
| 99 | + else: |
| 100 | + logging.info("Player #%d Cargo Full", ship.id) |
| 101 | + #eif |
| 102 | + logging.info("Done Collecting Baubles #%d", ship.id) |
| 103 | + |
| 104 | + def player_died(self, player, gone): |
| 105 | + # if ship destroyed, put baubles stored back |
| 106 | + for b in player.carrying: |
| 107 | + b.body.position = (player.object.body.position[0] + random.randint(-36, 36), player.object.body.position[1] + random.randint(-36, 36)) |
| 108 | + b.destroyed = False # reset so that it won't get cleaned up |
| 109 | + |
| 110 | + self.world.append(b) |
| 111 | + |
| 112 | + return super(TheHungerBaublesGame, self).player_died(player, gone) |
| 113 | + |
| 114 | + def game_get_extra_environment(self, player): |
| 115 | + v = 0 |
| 116 | + w = 0 |
| 117 | + for b in player.carrying: |
| 118 | + v += b.value |
| 119 | + w += b.weight |
| 120 | + baubles = [] |
| 121 | + for b in player.carrying: |
| 122 | + baubles.append({ "MASS": b.weight, "VALUE": b.value, "ID": b.id}) |
| 123 | + |
| 124 | + env = super(TheHungerBaublesGame, self).game_get_extra_environment(player) |
| 125 | + env.update({"POSITION": self.__cornucopia_position, "BAUBLES": baubles}) |
| 126 | + |
| 127 | + return env |
| 128 | + |
| 129 | + def game_get_extra_radar_info(self, obj, objdata, player): |
| 130 | + """ |
| 131 | + Called by the World when the obj is being radared |
| 132 | + """ |
| 133 | + super(TheHungerBaublesGame, self).game_get_extra_radar_info(obj, objdata, player) |
| 134 | + if hasattr(obj, "player"): |
| 135 | + objdata["NUMSTORED"] = len(obj.player.carrying) |
| 136 | + objdata["VALUE"] = self.get_player_cargo_value(obj.player) |
| 137 | + |
| 138 | + def player_get_stat_string(self, player): |
| 139 | + return str(int(player.bestscore)) + " - " + str(int(player.score)) + " in " + str(player.collected) + " : " + player.name + " w. " + str(self.get_player_cargo_weight(player)) |
| 140 | + |
| 141 | + def gui_draw_game_world_info(self, surface, flags, trackplayer): |
| 142 | + for player in self.game_get_current_player_list(): |
| 143 | + obj = player.object |
| 144 | + if obj != None: |
| 145 | + # draw number of objects carried |
| 146 | + text = debugfont().render(repr(len(player.carrying)), False, player.color) |
| 147 | + surface.blit(text, (obj.body.position[0]-30, obj.body.position[1]-4)) |
| 148 | + text = debugfont().render(repr(self.get_player_cargo_weight(player)), False, player.color) |
| 149 | + surface.blit(text, (obj.body.position[0]+30, obj.body.position[1]-4)) |
| 150 | + # draw line between player and HomeBase |
| 151 | + #if flags["DEBUG"] and self.__bases.has_key(player.netid): |
| 152 | + #pygame.draw.line(surface, player.color, intpos(obj.body.position), intpos(self.__bases[player.netid].body.position)) |
| 153 | + wrapcircle(surface, (255, 255, 0), self.__cornucopia_position, self.__cornucopia_radius, self.world.size, 3) |
| 154 | + |
| 155 | + # draw number of baubles carried by player |
| 156 | + |
| 157 | + def round_start(self): |
| 158 | + logging.info("Game Start") |
| 159 | + |
| 160 | + self.__spawned_num = 0 |
| 161 | + |
| 162 | + super(TheHungerBaublesGame, self).round_start() |
| 163 | + |
| 164 | + def world_create(self): |
| 165 | + super(TheHungerBaublesGame, self).world_create() |
| 166 | + |
| 167 | + self.__cornucopia_position = getPositionAwayFromOtherObjects(self.world, self.cfg.getint("TheHungerBaubles", "cornucopia_buffer_object"), self.cfg.getint("TheHungerBaubles", "cornucopia_buffer_edge")) |
| 168 | + |
| 169 | + #TODO: Remove anything left inside cornucopia? |
0 commit comments