def update(self): # health regen/degen if self.hps_regen != 0: self.hp_current = min( self.hp_current + (self.hps_regen * self.game.delta_time), self.hp_max) # face the player if he's close enough to be seen player_dist = calc_dist(self.pos, self.game.player.pos) if player_dist <= self.vision_distance: self.rotate(Vec2(self.game.player.hit_rect.center)) else: self.rot = randint(0, 360) self.image = pg.transform.rotate(self.orig_image, self.rot) self.acc = Vec2(self.speed, 0).rotate(-self.rot) # update image # TODO: give these guys some animation self.rect = self.image.get_rect(center=self.rect.center) self.rect.center = self.pos # ajdust angle tp spread out from other mobs self.avoid(self.game.mobs, self.avoid_radius) # run forwards if player_dist <= self.vision_distance: self.acc.scale_to_length(self.speed) self.acc += self.vel * -1 self.vel += self.acc * self.game.delta_time self.pos += self.vel * self.game.delta_time + 0.5 * self.acc * self.game.delta_time**2 else: self.acc.scale_to_length(self.speed * .3) self.acc += self.vel * -1 self.vel += self.acc * self.game.delta_time self.pos += self.vel * self.game.delta_time + 0.5 * self.acc * self.game.delta_time**2 # wall collision self.hit_rect.centerx = self.pos.x self.collide(self.game.walls, 'x') self.hit_rect.centery = self.pos.y self.collide(self.game.walls, 'y') # mouseover highlighting if self.rect.collidepoint(pg.mouse.get_pos() - self.game.camera.offset): # self.image = self.get_outline self.image.blit(self.get_outline(), self.image.get_rect()) # death conditions check if self.hp_current <= 0: self.die()
def process_input(self): self.vel = Vec2( 0, 0 ) # this might be a problem later on, if external forces can effect player position keys = pg.key.get_pressed() # rotational movement if self.game.configs.control_scheme == 'rotational': if keys[pg.K_LEFT] or keys[pg.K_a]: self.vel = Vec2(self.speed, 0).rotate(-self.rot - 90) if keys[pg.K_RIGHT] or keys[pg.K_d]: self.vel = Vec2(self.speed, 0).rotate(-self.rot + 90) if keys[pg.K_UP] or keys[pg.K_w]: self.vel = Vec2(self.speed, 0).rotate(-self.rot) if keys[pg.K_DOWN] or keys[pg.K_s]: self.vel = Vec2(-self.speed, 0).rotate( -self.rot) # no backwards speed penalty if self.game.configs.control_scheme == '4d': if keys[pg.K_LEFT] or keys[pg.K_a]: self.vel += Vec2(self.speed, 0).rotate(180) if keys[pg.K_RIGHT] or keys[pg.K_d]: self.vel += Vec2(self.speed, 0).rotate(0) if keys[pg.K_UP] or keys[pg.K_w]: self.vel += Vec2(self.speed, 0).rotate(270) if keys[pg.K_DOWN] or keys[pg.K_s]: self.vel += Vec2(-self.speed, 0).rotate(270) # no backwards speed penalty # skills # switch focus skill if keys[pg.K_PAGEDOWN]: if self.can_change_skills: self.focus_skill = next(self.all_skills_gen) self.last_skill_change = pg.time.get_ticks() # switch focus bonus if keys[pg.K_PAGEUP]: if self.can_change_skills and self.focus_skill: self.focus_skill.next_focus() self.last_skill_change = pg.time.get_ticks() # active skill if pg.mouse.get_pressed()[0]: self.equipped['active_skill'].fire() # melee attack if keys[pg.K_SPACE] or pg.mouse.get_pressed()[2]: self.equipped['melee_skill'].fire() # movement skill if keys[pg.K_LCTRL]: self.equipped['move_skill'].fire()
def __init__(self, game, name, owner, image, damage, pos, vel, duration, align='center', moves_with_owner=False): self._layer = layers.projectile self.groups = game.all_sprites, game.aoe pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.owner = owner self.name = name self.image = image self.rect = self.image.get_rect() self.pos = Vec2(pos) self.rect.center = pos self.vel = vel self.duration = duration self.damage = damage self.damage_rate = 2000 self.spawn_time = pg.time.get_ticks() self.moves_with_owner = moves_with_owner self.align = align
def __init__(self, game, start_pos): # pygame sprite stuff self._layer = layers.mob self.groups = game.all_sprites, game.mobs pg.sprite.Sprite.__init__(self, self.groups) # object references self.game = game # assets self.standing_frames = None self.load_images() # graphics self.image = self.standing_frames[0] self.orig_image = self.image # physics self.rect = self.image.get_rect(center=start_pos) self.hit_rect = pg.Rect(0, 0, settings.TILESIZE - 5, settings.TILESIZE - 5) self.hit_rect.center = self.rect.center self.vel = Vec2(0, 0) self.acc = Vec2(0, 0) self.pos = Vec2(start_pos) self.rot = 0 self.avoid_radius = 100 # state self.last_damage = defaultdict(int) # default stats self.speed = 80 self.hp_current = 100 self.hp_max = 100 self.hps_regen = 0 self.collision_damage = 10 self.damage_rate = 200 self.collision_knockback = 20 self.vision_distance = 300 self.xp_value = 10 # item management self.inventory = [] self.food = randint(5, 20)
def mouse_angle(self): x1, y1 = self.game.camera.apply(self).center x2, y2 = Vec2(pg.mouse.get_pos()) dx = x2 - x1 dy = y2 - y1 rads = atan2(dy, dx) rads %= 2 * pi degs = int(degrees(rads)) + 90 return degs % 360
def rotate(self, target): """ Turn to face the target :param target: pygame.math.Vector2 :return: None """ self.rot = (target - self.hit_rect.center).angle_to(Vec2(1, 0)) self.image = pg.transform.rotate(self.orig_image, self.rot)
def generate_maptiles(self): """ loops through self.map.data and spawns walls currently, this function also sets the player start position when it finds an empty tile - this is kind of an efficiency hack since we're looping through the data anyways, but might need to be replaced later to separate functionality or as part of procedural gen """ mob_types = [ self.worldmap.graph.node[self.worldmap.current_node]['mobtype'] ] if self.worldmap.destination_node: mob_types += [ self.worldmap.graph.node[self.worldmap.destination_node] ['mobtype'] ] for x in range(self.current_map.tilewidth): for y in range(self.current_map.tileheight): if self.current_map.data[x][y] == 1: self.spawn(Wall, (x * settings.TILESIZE, y * settings.TILESIZE)) elif self.current_map.player_start is None: tile_center_x = x * settings.TILESIZE + settings.TILESIZE / 2 tile_center_y = y * settings.TILESIZE + settings.TILESIZE / 2 self.current_map.player_start = Vec2( int(tile_center_x), int(tile_center_y)) if self.configs.debug: print("Player starting coordinates set to: {}".format( self.current_map.player_start)) else: # distance from player spawn player_dist = calc_dist( (x * settings.TILESIZE, y * settings.TILESIZE), self.current_map.player_start) # distance from other clusters cluster_space = not any([ calc_dist((x, y), cluster) < settings.cluster_dist for cluster in self.current_map.clusters ]) if player_dist > settings.safe_spawn_dist and cluster_space: # random.random() > .9: # self.spawn(Mob, (x * settings.TILESIZE, y * settings.TILESIZE)) self.current_map.clusters.append((x, y)) for cluster in self.current_map.clusters: for i in range(settings.pack_size): x = (cluster[0] * settings.TILESIZE + i) + (settings.TILESIZE // 2) y = (cluster[1] * settings.TILESIZE + i) + (settings.TILESIZE // 2) self.spawn(choice(mob_types), (x, y))
def handle_event(self, event): # left click if event.type == pg.MOUSEBUTTONDOWN and event.button == 1: self.highlight() button_up_relative_pos = Vec2(event.pos) - Vec2( self.button_up.get_abs_offset()) - Vec2(self.rect.topleft) button_down_relative_pos = Vec2(event.pos) - Vec2( self.button_down.get_abs_offset()) - Vec2(self.rect.topleft) if self.button_up.get_rect().collidepoint(button_up_relative_pos): print('button up clicked') if self.index < len(self.content_left) - self.items_per_screen: self.index += 1 if self.button_down.get_rect().collidepoint( button_down_relative_pos): print('button down clicked') if self.index: self.index -= 1 # scroll wheel up elif event.type == pg.MOUSEBUTTONDOWN and event.button == 4: if self.index: self.index -= 1 # scroll wheel down elif event.type == pg.MOUSEBUTTONDOWN and event.button == 5: if self.index < len(self.content_left) - self.items_per_screen: self.index += 1
def __init__(self, game, image, damage, pos, vel, duration, kickback): self.groups = game.all_sprites, game.projectiles pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = image self.rect = self.image.get_rect() self.pos = Vec2(pos) self.rect.center = pos self.vel = vel self.duration = duration self.kickback = kickback self.damage = damage self.damage_rate = 2000 self.spawn_time = pg.time.get_ticks()
def fire(self): spawn_point = self.owner.projectile_spawn proj_direction = Vec2(1, 0).rotate(-self.owner.rot) proj_vel = proj_direction * self.proj_speed proj_vel += self.owner.vel # no need to save if self.can_fire: MovingDamageArea(game=self.game, name=self.name, owner=self.owner, image=self.rotated_img, damage=self.proj_damage, pos=spawn_point, vel=proj_vel, duration=self.proj_duration, align=self.aligns[self.owner.facing], moves_with_owner=True) self.last_fired = pg.time.get_ticks() self.owner.attacking = True
def update(self): """ update logic for main game loop """ self.effects_screen.fill((0, 0, 0, 0)) self.all_sprites.update() self.camera.update(target=self.player, hit_rect=True) self.trigger_delayed_events() for skill in self.active_skills: skill.update() # projectiles hit mobs hits = pg.sprite.groupcollide(self.mobs, self.projectiles, False, True) for hit in hits: hit.take_damage(hits[hit][0]) # hit.hp_current -= hits[hit][0].damage # mobs take area damage hits = pg.sprite.groupcollide(self.mobs, self.aoe, False, False) for hit in hits: hit.take_damage(hits[hit][0]) # hit.hp_current -= hits[hit][0].damage # mobs hit player hits = pg.sprite.spritecollide(self.player, self.mobs, False, Collider.collide_hit_rect) for hit in hits: # self.player.hp_current -= hit.collision_damage self.player.take_damage(hits[0]) if hits: # if : self.player.pos += Vec2(hits[0].collision_knockback, 0).rotate(-hits[0].rot) if len(self.mobs) == 0: print('All mobs defeated') self.flash_message('All Mobs Defeated', 3) if not self.worldmap.destination_node: self.fsm('select_destination') else: self.travel()
def update(self, action): if action[0] == 1: self.angle += max_turn_rate if action[1] == 1: self.angle -= max_turn_rate if self.timestep % 300 == 0: n = random.randint(0, 100) if n <= cut_percentage: self.append_history = False if self.t_cut == cut_len: self.append_history = True self.t_cut = 0 position = self.position + Vec2(1, 0).rotate(self.angle) * speed if self.append_history: self.history.append(position) else: self.t_cut += 1 self.position = position self.timestep += 1
def __init__(self, px, py, pz, rx, ry, rz, sx, sy, sz): self.pos = Vec(px, py, pz) self.rotation = Vec(rx, ry, rz) self.size = Vec(sx, sy, sz) self.load_image() self.image_size = Vec2(self.image.get_size()) self.plate = '' self.font = pygame.font.Font('UKNumberPlate.ttf', 290) self.verts = [ Vec(-1, -1, -1), Vec(-1, -1, 1), Vec(1, -1, 1), Vec(1, -1, -1), Vec(-1, 1, -1), Vec(-1, 1, 1), Vec(1, 1, 1), Vec(1, 1, -1), ] self.faces = [(3, 7, 6, 2), (4, 3, 7, 8), (1, 4, 8, 5), (2, 1, 5, 6), (2, 3, 4, 1), (6, 7, 8, 5)]
def __init__(self, game, start_pos): # pygame sprite stuff self._layer = layers.player self.groups = game.all_sprites pg.sprite.Sprite.__init__(self, self.groups) super().__init__() self.name = 'Player' # object references self.game = game # assets self.standing_frames = None self.moving_frames = None self.attacking_frames = None self.load_images() # graphics self.last_update = pg.time.get_ticks() self.frame_delay = 200 # self.image = next(self.standing_frames['down']) self.image = next(self.standing_frames['S']) self.orig_image = self.image # physics self.rect = self.image.get_rect(center=start_pos) self.hit_rect = pg.Rect(0, 0, 30, 60) self.hit_rect.midbottom = self.rect.midbottom self.vel = Vec2(0, 0) # self.vx, self.vy = 0, 0 # self.x, self.y = start_pos self.pos = Vec2(start_pos) self.rot = 0 self.proj_offset = Vec2(15, 15) # hardcoded to the placeholder graphics # state self.last_damage = defaultdict(int) self.dead = False self.last_shot = 0 self.last_skill_change = 0 self.focus_skill = None self.attacking = False self.speed_mul = 1.0 # self.last_positions = Queue(maxsize=10) # default stats self.vision_radius = 300 self.skill_change_delay = 100 self.xp_total = 0 self.speed = 100 self.hp_current = 80 self.hp_max = 100 self.hps_regen = 1 # hp per second self.resource_current = 50 self.resource_max = 100 self.rps_regen = 3 # resource per second self.eating_rate = 1 # food per second self.starving_penalties = {'speed': 50} # item management self.food = 100 self.inventory = [] self.equipped = { 'armor': None, 'weapon': None, 'active_skill': None, 'melee_skill': None, 'move_skill': None, 'passives': [] } self.load_placeholder_skills() self.all_skills_gen = cycle(self.all_skills)
def display(self, screen): self.load_image() self.add_number() polygon = [] verts = [] for v in self.verts: cv = Vec(v.x, v.y, v.z) cv.x *= self.size.x cv.y *= self.size.y cv.z *= self.size.z cv = cv.rotate_x_rad(radians(self.rotation.x)) cv = cv.rotate_y_rad(radians(self.rotation.y)) cv = cv.rotate_z_rad(radians(self.rotation.z)) cv.x += self.pos.x cv.y += self.pos.y cv.z += self.pos.z verts.append(cv) ps = [] front = None for i1, i2, i3, i4 in map(lambda f: tuple([i - 1 for i in f]), self.faces): polygon = [ get(verts[i1]), get(verts[i2]), get(verts[i3]), get(verts[i4]) ] if self.faces[2] == (i1 + 1, i2 + 1, i3 + 1, i4 + 1): front = polygon ps.append(polygon) ps.sort(key=distance_sorter, reverse=True) for p in ps: check = p p = list(map(lambda elem: elem[:2], p)) pygame.draw.polygon(screen, [150, 150, 0], p) pygame.draw.polygon(screen, [0, 0, 0], p, 1) if check == front: top_left = Vec2(p[0]) top_right = Vec2(p[1]) bottom_right = Vec2(p[2]) bottom_left = Vec2(p[3]) start = Vec2(p[0]) end = Vec2(p[1]) current = Vec2(p[0]) x_move = (end - start).normalize() y_move = (bottom_left - top_left).normalize() while True: current += x_move draw = True uv = Vec2( translate(current.x, start.x, end.x, 0, self.image_size.x), translate(current.y, top_left.y, bottom_left.y, 0, self.image_size.y)) try: c = self.image.get_at((int(uv.x), int(uv.y))) except IndexError: draw = False if draw: screen.set_at((int(current.x), int(current.y)), c) if abs(current.x - end.x) + abs(current.y - end.y) < 1: start += y_move end += y_move current = Vec2(start.x, start.y) if abs(start.x - bottom_left.x) + abs(start.y - bottom_left.y) < 1: break
from pygame.math import Vector2 as Vec2 moves = [] with open('input.txt') as f: moves = f.readline().split(", ") cur_pos = Vec2(0, 0) DIRECTION = { 'N': Vec2(0, 1), 'S': Vec2(0, -1), 'E': Vec2(-1, 0), 'W': Vec2(1, 0) } cur_direction = 'N' DIRECTION_MAP = { 'N': { 'R': 'E', 'L': 'W' }, 'S': { 'R': 'W', 'L': 'E' }, 'E': { 'R': 'S', 'L': 'N' }, 'W': {
def mouse_pos(self): return Vec2(pg.mouse.get_pos()) - self.camera.offset
import pygame from game import Game from fever import Curve from pygame.math import Vector2 as Vec2 import random import numpy as np import matplotlib.pyplot as plt game = Game(640, 480) curve = Curve(Vec2(100, 100)) game.curve = curve while (1): action = random.choice([0, 1, 2]) frame, reward = game.step(action)
def rotate(self, target): """ face the target """ self.rot = (target - self.hit_rect.center).angle_to(Vec2(1, 0))
def random_disk(): sqrtr = random.random()**0.5 theta = 2.0 * pi * random.random() return sqrtr * Vec2(cos(theta), sin(theta))