gm techniques – How can I quickly get a player back into a session after their character dies?

This varies somewhat by the tone of your campaign and the system/setting.

In some systems/settings, resurrections are relatively easy. In that case, the obvious answer is to perform the resurrection with some sort of minor penalty and then go on. This, though, cheapens character death. In a mostly hack ‘n slash, lighthearted game, this is perfectly fine and essentially replicates the feeling of most videogames (you died, now you loose a little bit of progress and get to try again). In a more serious game with a deep story, knowing death is cheap can affect the story (sacraficing your life means a lot less if that life comes back at the price of a little gold and XP or whatever) and knowing it is not just available but cheap will definitely affect the way the characters play. It will make them more likely to take large risks. (again whether that is good or bad depends on what you are going for).

An alternative, again available in some but not all settings is that they come back as a ghost or other undead form. This was interesting in some oWoD games I played, but probably does not work well in say DnD. You have to be in a setting that supports that and it would have to be such that a ghost could integrate without messing up the story, or this becomes a very bad option.

The next option of course is to have backups standing by. This could mean having a new character already generated, or having the player make one quickly while everyone else continues on and then integrating them as soon as ready. This works well in games where character creation is fairly quick, but less well when it takes a while, and it is complicated if the players are expected to make up an elaborate backstory for their character. One way to simplify this, though one that is rarely satisfying, is to let them bring back a variant of their old character. Tweak the name, maybe reassign a skill or two, and tweak the backstory a bit, but basically let them reuse the character that died.

Finally, use deus ex machina to prevent the death. Personally, I hate this option. It seems to cheapen death even more than resurrection, and basically changes what just happened. But as long as it is not overused, it can be a way of saving a character that someone put a lot of time and effort into developping, with a long backstory even in settings where resurrection is just not an option.

gm techniques – A player loves the story and the combat but doesn’t role-play

Together with my best friend Jon, we’re in a group of people who enjoy RPG’s. I’m GMing for several years in this larger group. Other friends of that group also GM. I’m the most story-oriented GM, the other GMs are mostly one-shots and Door-Monster-Treasure oriented.

Recently, we started a new campaign. I’m GMing and there are 5 other players, including Jon, for the first time in a group with me. That campaign, I said from the start, even when only pitching it, would be very story-oriented and there would not be many combats. So every player made their character focusing on that. Jon doesn’t read much English so we built his character together. His pitch for the character was that he likes to hit and we made a very fight-oriented character. That’s OK, even though I reminded him that there wouldn’t be many combats.

Now in session 1 and 2, there were combat moments, so Jon was happy. But session 3 came and it was mostly a downtime session. Jon was disappointed that there weren’t many combats and made his character look for illegal fights to make some bucks. Fine, so we did that, and it was great as I surprised the players with some tricks.

Now, I saw Jon during that session 3 and basically he didn’t speak much. He let the story flow and was following the story, actively, reacted to it outside-the-game, but did nothing much in-game except following other characters. Other players weren’t really aware that Jon’s character was mostly passive except for the illegal fight as they were having real fun and they didn’t see the time fly.

I’ve spoken with Jon and he told me that he was a bit sad there wasn’t more combat, but he really enjoyed the story unfolding before him, and he excitedly looks forward to the next session, even though I told him it’d be like this session 3 where I plan no combat.

Separately, Jon really wanted me to introduce his GF to D&D so last week I GM’d a one-shot for Jon, his GF and his GF’s sister (who incidentally also loves D&D, but is nowhere in my usual groups). For that one-shot, I used Candlekeep Mysteries’ level 1 story, removed a few monsters because there were too many for only 3 players. And again Jon was there to follow the story, genuinely enjoying it outside-the-game, but the two in-game drivers were his GF (very good player for a first-time player) and her sister. Jon’s character did nothing but the fighting bits or providing help when needed.

I know that the important is that everybody has fun in the games, but I want to make sure that these sessions appeal to everyone, including Jon.

I will definitely speak with Jon more about this topic, but I’m wondering if I should completely change my view on my campaign, making it more combat-oriented that I intended despite the initial expectation that it’d be a story-based campaign? If so, how should I handle this? Also, will Jon be a problem-player? If yes, how should I handle that part?

unity – Sticking the Rigidbody2D player to a moving platform without parenting & transform fiddling

I have a player entity with Rigidbody2D component and I have a moving platform which is a kinematic Rigidbody2D. Player movement is done by setting it’s velocity (body.velocity = newVelocity) and platform is moved via body.MovePosition.

I’ve made it so that the platform has a sensor which, when triggered, catches the Rigidbody2D of the entity that is on (currently only does that for player) and then I tried the following:

  1. Moving the player along the platform with caughtRigidbody.MovePosition. This keeps the player on the platform but the player is unable to move. It seems that MovePosition overrides any velocity change on the player and keeps him on the platform indefinitely. This would be ideal if I could have this behavior but keeping player movement.

  2. Moving the caught rigidbody by adding platform velocity to the body but it seems jittery and also happens to behave strangely when platform direction changes.

I got the player movement how I want it so I’m not willing to tear out the whole movement code and change the player to kinematic or something like that.

This is the relevant platform code:

public class MovingPlatform
{
    private void FixedUpdate()
    {
        // Only one node (initial position). Nowhere to move to
        if (worldNodes.Length == 1)
        {
            return;
        }

        // Target position reached?
        if (body.position == worldNodes(index))
        {
            // Is last (or first in backwards direction) target?
            if (direction == Direction.Forwards && index == worldNodes.Length - 1 ||
                direction == Direction.Backwards && index == 0)
            {
                // Change direction (forwards = 1, backwards = -1)
                direction = (Direction) ((int) direction * -1);
            }

            // set next target index
            index += (int) direction;
        }

        // Get target
        Vector2 target = worldNodes(index);
        // Get current platform position
        Vector2 position = body.position;
        // Calculate single-frame movement towards target
        Vector2 movementThisFrame = Vector2.MoveTowards(position, target, settings.Speed * Time.deltaTime);
        // Move platform by calculated movement
        body.MovePosition(movementThisFrame);
        // Calculate platform movement velocity (displacement / time delta)
        velocity = (movementThisFrame - position) / Time.deltaTime;
        MoveCaughtRigidbodies();
    }

    private void MoveCaughtRigidbodies()
    {
        foreach (Rigidbody2D caughtRigidbody in caughtRigidbodies)
        {
            // This keeps the player on the platform without jittering, but the player cant move
            //caughtRigidbody.MovePosition(caughtRigidbody.position + body.position - lastPosition);

            // This is spotty. It launches the player off the platform sometime when the platform changes direction
            // if (caughtRigidbody.velocity != velocity)
            // {
            //     caughtRigidbody.velocity += velocity;   
            // }
        }

        lastPosition = body.position;
    }
}

dnd 5e – Do Player characters know they are under the effect of a Death Tyrant’s Negative Energy Cone?

At least, not until specific things occur as a result of being in the cone.

Targets (of spells) PHB 204

Unless a spell has a perceptible effect, a creature might not know it
was targeted by a spell at all. An effect like crackling lightning is
obvious, but a more subtle effect, such as an attempt to read a
creature’s thoughts, typically goes unnotice, unless a spell says
otherwise.

While the Negative Energy Cone isn’t a spell, it is a magical effect, and so it is reasonable to apply the same logic.

Death Tyrant MM 29

The death tyrant’s central eye emits an invisible, magical 150-foot
cone of negative energy. At the start of each of its turns, the tyrant
decides which way the cone faces and whether the cone is active.

Any
creature in that area can’t regain hit points. Any humanoid that dies
there becomes a zombie
under the tyrant’s command. The dead humanoid
retrains its place in the initiative order and animates at the start
of its next turn, provided that its body hasn’t been completely
destroyed.

Nothing in the description of the ability describes any obvious effect, other than when trying to regain hit points or dying, so creatures won’t notice it unless either of those two things occur.

DMs may allow checks to notice where the central eye is looking

Given that the cone is emitted by the central eye, a DM may reasonably allow a character to try to determine where the cone is being directed, if said character is aware that such a cone exists. However, this is totally up to the DM as there is no specific guidance on this.

Official rules concur

The Sage Advice Compendium contains additional detailed guidance on perceiving spell effects, so again, the logic applies to our magical effect here:

Do you always know when you’re under the effect of a spell?

You’re aware that a spell is affecting you if it has a perceptible effect or if its text says you’re aware of it (see PHB , under “Targets”). Most spells are obvious. For example, fireball burns you, cure wounds heals you, and command forces you to suddenly do something you didn’t intend. Certain spells are more subtle, yet you become aware of the spell at a time specified in the spell’s description. Charm person and detect thoughts are examples of such spells.

Some spells are so subtle that you might not know you were ever under their effects. A prime example of that sort of spell is suggestion. Assuming you failed to notice the spellcaster casting the spell, you might simply remember the caster saying, “The treasure you’re looking for isn’t here. Go look for it in the room at the top of the next tower.” You failed your saving throw, and off you went to the other tower, thinking it was your idea to go there. You and your companions might deduce that you were beguiled if evidence of the spell is found. It’s ultimately up to the DM whether you discover the presence of inconspicuous spells. Discovery usually comes through the use of skills like Arcana, Investigation, Insight, and Perception or through spells like detect magic.

dnd 5e – Does Iron Flask work on player characters?

The flask has no effect on most PCs while on the Material Plane

When you target a creature with the flask:

If the target is native to a plane of existence other than the one you’re on, the target must succeed on a DC 17 Wisdom saving throw or be trapped in the flask.

This effect only happens for creatures not native to the current plane. No effect is specified for a target that is native to the plane of existence, which means that if you are on the Material Plane and target a creature native to the Material Plane, the flask has no effect. The vast majority of playable races are native to the Material Plane, so they generally cannot be trapped by the flask under normal circumstances. However, there are exceptions, such as Eladrin (mechanically a sub-race of elves), who are “native to the Feywild”. An eladrin on the Material Plane can be affected by the flask.

However, if the party were to make an excursion to another plane, such as the Feywild, the PCs would indeed be vulnerable to the flask’s effect while they are not on the Material Plane. Conversely, an Eladrin PC would be immune to the flask while on the Feywild, since it is their native plane.

It may even be beneficial for a PC to use the flask on another PC under some rare circumstances, since the requirement to obey another PC’s orders might help override an enemy charm or mind control effect. This would obviously require quite a lot of trust, both in and out of character.

dnd 5e – Does Iron Flask work on player characters?

dnd 5e – Does Iron Flask work on player characters? – Role-playing Games Stack Exchange

collision detection – player disappears when collides with enemy

I was making a game and then when I tested it out, if I keep on colliding with the enemy, the player’s image just disappears but the rect is still there.

main.py:

import pygame as pg
import sys
from random import choice, random
from os import path
from settings import *
from sprites import *
from tilemap import *

# HUD functions
def draw_player_health(surf, x, y, pct):
    if pct < 0:
        pct = 0
    BAR_LENGTH = 100
    BAR_HEIGHT = 20
    fill = pct * BAR_LENGTH
    outline_rect = pg.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
    fill_rect = pg.Rect(x, y, fill, BAR_HEIGHT)
    if pct > 0.6:
        col = GREEN
    elif pct > 0.3:
        col = YELLOW
    else:
        col = RED
    pg.draw.rect(surf, col, fill_rect)
    pg.draw.rect(surf, WHITE, outline_rect, 2)

class Game:
    def __init__(self):
        pg.mixer.pre_init(44100, -16, 4, 2048)
        pg.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.load_data()

    def draw_text(self, text, font_name, size, color, x, y, align="topleft"):
        font = pg.font.Font(font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect(**{align: (x, y)})
        self.screen.blit(text_surface, text_rect)

    def load_data(self):
        game_folder = path.dirname(__file__)
        self.img_folder = path.join(game_folder, 'img')
        self.font_folder = path.join(game_folder, 'fonts')
        self.weapon_folder = path.join(game_folder, 'weapons')
        self.snd_folder = path.join(game_folder, 'snd')
        self.music_folder = path.join(game_folder, 'music')
        self.item_folder = path.join(game_folder, 'items')
        self.potion_folder = path.join(self.item_folder, 'potions')
        self.map_folder = path.join(game_folder, 'maps')
        self.monster_folder = path.join(game_folder, 'enemies')
        self.title_font = path.join(self.font_folder, 'AlegreyaSC-Italic.ttf')
        self.hud_font = path.join(self.font_folder, 'AlegreyaSC-Italic.ttf')
        self.dim_screen = pg.Surface(self.screen.get_size()).convert_alpha()
        self.dim_screen.fill((0, 0, 0, 180))
        self.player_img = pg.image.load(path.join(self.img_folder, PLAYER_IMG)).convert_alpha()
        self.bullet_images = {}
        self.bullet_images('lg') = pg.image.load(path.join(self.weapon_folder, BULLET_IMG)).convert_alpha()
        self.bullet_images('sm') = pg.transform.scale(self.bullet_images('lg'), (10, 10))
        self.mob_img = pg.image.load(path.join(self.monster_folder, MOB_IMG)).convert_alpha()
        self.splat = pg.image.load(path.join(self.img_folder, SPLAT)).convert_alpha()
        self.splat = pg.transform.scale(self.splat, (64, 64))
        self.item_images = {}
        for item in ITEM_IMAGES:
            # Todo: give each item a type, and make it like path.join(f'{item(type)}_folder, ITEM_IMAGES(item)')
            self.item_images(item) = pg.image.load(path.join(self.potion_folder, ITEM_IMAGES(item))).convert_alpha()        # Sound loading
        pg.mixer.music.load(path.join(self.music_folder, BG_MUSIC))
        self.effects_sounds = {}
        for type in EFFECTS_SOUNDS:
            self.effects_sounds(type) = pg.mixer.Sound(path.join(self.snd_folder, EFFECTS_SOUNDS(type)))
        self.weapon_sounds = {}
        for weapon in WEAPON_SOUNDS:
            self.weapon_sounds(weapon) = ()
            for snd in WEAPON_SOUNDS(weapon):
                s = pg.mixer.Sound(path.join(self.snd_folder, snd))
                s.set_volume(0.3)
                self.weapon_sounds(weapon).append(s)
        self.zombie_moan_sounds = ()
        for snd in ZOMBIE_MOAN_SOUNDS:
            s = pg.mixer.Sound(path.join(self.snd_folder, snd))
            s.set_volume(0.2)
            self.zombie_moan_sounds.append(s)
        self.player_hit_sounds = ()
        for snd in PLAYER_HIT_SOUNDS:
            self.player_hit_sounds.append(pg.mixer.Sound(path.join(self.snd_folder, snd)))
        self.zombie_hit_sounds = ()
        for snd in ZOMBIE_HIT_SOUNDS:
            self.zombie_hit_sounds.append(pg.mixer.Sound(path.join(self.snd_folder, snd)))

    def new(self, map_name):
        # initialize all variables and do all the setup for a new game
        self.all_sprites = pg.sprite.LayeredUpdates()
        self.walls = pg.sprite.Group()
        self.mobs = pg.sprite.Group()
        self.bullets = pg.sprite.Group()
        self.items = pg.sprite.Group()
        self.portals = pg.sprite.Group()
        self.map = TiledMap(path.join(self.map_folder, map_name))
        self.map_img = self.map.make_map()
        self.map.rect = self.map_img.get_rect()
        for tile_object in self.map.tmxdata.objects:
            obj_center = vec(tile_object.x + tile_object.width / 2,
                             tile_object.y + tile_object.height / 2)
            if tile_object.name == 'player':
                self.player = Player(self, obj_center.x, obj_center.y)
            if tile_object.name == 'zombie':
                Mob(self, obj_center.x, obj_center.y)
            if tile_object.name == "https://gamedev.stackexchange.com/#":
                Obstacle(self, tile_object.x, tile_object.y,
                         tile_object.width, tile_object.height)
            if tile_object.name in ('health', 'shotgun'):
                Item(self, obj_center, tile_object.name)
            # delete this if cant work!!!
            if tile_object.name == 'portal':
                Portal(self, tile_object.x, tile_object.y,
                       tile_object.width, tile_object.height, tile_object.type)


        self.camera = Camera(self.map.width, self.map.height)
        self.draw_debug = False
        self.paused = False
        self.night = False
        self.effects_sounds('level_start').play()

    def run(self):
        # game loop - set self.playing = False to end the game
        self.playing = True
        pg.mixer.music.play(loops=-1)
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000.0  # fix for Python 2.x
            self.events()
            if not self.paused:
                self.update()
            self.draw()

    def quit(self):
        pg.quit()
        sys.exit()

    def update(self):
        # update portion of the game loop
        self.all_sprites.update()
        self.camera.update(self.player)
        # player hits items
        hits = pg.sprite.spritecollide(self.player, self.items, False)
        for hit in hits:
            if hit.type == 'health' and self.player.health < PLAYER_HEALTH:
                hit.kill()
                self.effects_sounds('health_up').play()
                self.player.add_health(HEALTH_PACK_AMOUNT)
            if hit.type == 'shotgun':
                hit.kill()
                self.effects_sounds('gun_pickup').play()
                self.player.weapon = 'shotgun'
        # mobs hit player
        hits = pg.sprite.spritecollide(self.player, self.mobs, False, collide_hit_rect)
        for hit in hits:
            if random() < 0.7:
                choice(self.player_hit_sounds).play()
            self.player.health -= MOB_DAMAGE
            hit.vel = vec(0, 0)
            if self.player.health <= 0:
                self.playing = False
        if hits:
            self.player.hit()
            self.player.pos += vec(MOB_KNOCKBACK, 0).rotate(-hits(0).rot)
        # bullets hit mobs
        hits = pg.sprite.groupcollide(self.mobs, self.bullets, False, True)
        for mob in hits:
            # hit.health -= WEAPONS(self.player.weapon)('damage') * len(hits(hit))
            for bullet in hits(mob):
                mob.health -= bullet.damage
            mob.vel = vec(0, 0)

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))


    def draw(self):
        pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
        # self.screen.fill(BGCOLOR)
        self.screen.blit(self.map_img, self.camera.apply(self.map))
        # self.draw_grid()
        for sprite in self.all_sprites:
            if isinstance(sprite, Mob):
                sprite.draw_health()
            self.screen.blit(sprite.image, self.camera.apply(sprite))
            if self.draw_debug:
                pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(sprite.hit_rect), 1)
        if self.draw_debug:
            for wall in self.walls:
                pg.draw.rect(self.screen, CYAN, self.camera.apply_rect(wall.rect), 1)

        # pg.draw.rect(self.screen, WHITE, self.player.hit_rect, 2)
        # HUD functions
        draw_player_health(self.screen, 10, 10, self.player.health / PLAYER_HEALTH)
        self.draw_text('Zombies: {}'.format(len(self.mobs)), self.hud_font, 30, WHITE,
                       WIDTH - 10, 10, align="topright")
        if self.paused:
            self.screen.blit(self.dim_screen, (0, 0))
            self.draw_text("Paused", self.title_font, 105, RED, WIDTH / 2, HEIGHT / 2, align="center")
        pg.display.flip()

    def events(self):
        # catch all events here
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.quit()
                if event.key == pg.K_h:
                    self.draw_debug = not self.draw_debug
                if event.key == pg.K_p:
                    self.paused = not self.paused
                if event.key == pg.K_n:
                    self.night = not self.night

    def show_start_screen(self):
        pass

    def show_go_screen(self):
        self.screen.fill(BLACK)
        self.draw_text("GAME OVER", self.title_font, 100, RED,
                       WIDTH / 2, HEIGHT / 2, align="center")
        self.draw_text("Press a key to start", self.title_font, 75, WHITE,
                       WIDTH / 2, HEIGHT * 3 / 4, align="center")
        pg.display.flip()
        self.wait_for_key()

    def wait_for_key(self):
        pg.event.wait()
        waiting = True
        while waiting:
            self.clock.tick(FPS)
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    waiting = False
                    self.quit()
                if event.type == pg.KEYUP:
                    waiting = False

thegame.py

from main import *

#the game!
g = Game()
while True:

sprites.py

import pygame as pg
from random import uniform, choice, randint, random
from settings import *
from tilemap import collide_hit_rect
import pytweening as tween
from itertools import chain
vec = pg.math.Vector2

def collide_with_walls(sprite, group, dir):
    if dir == 'x':
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            if hits(0).rect.centerx > sprite.hit_rect.centerx:
                sprite.pos.x = hits(0).rect.left - sprite.hit_rect.width / 2
            if hits(0).rect.centerx < sprite.hit_rect.centerx:
                sprite.pos.x = hits(0).rect.right + sprite.hit_rect.width / 2
            sprite.vel.x = 0
            sprite.hit_rect.centerx = sprite.pos.x
    if dir == 'y':
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            if hits(0).rect.centery > sprite.hit_rect.centery:
                sprite.pos.y = hits(0).rect.top - sprite.hit_rect.height / 2
            if hits(0).rect.centery < sprite.hit_rect.centery:
                sprite.pos.y = hits(0).rect.bottom + sprite.hit_rect.height / 2
            sprite.vel.y = 0
            sprite.hit_rect.centery = sprite.pos.y

def collide_with_portal(game, destination, sprite, group, direction):
    # todo: copy paste above and make it into the portal thing and look at tutorials
    if direction == 'y':
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            if hits(0).rect.centery > sprite.hit_rect.centery:
                sprite.pos.y = hits(0).rect.top - sprite.hit_rect.height / 2
            if hits(0).rect.centery < sprite.hit_rect.centery:
                sprite.pos.y = hits(0).rect.bottom + sprite.hit_rect.height / 2
            sprite.vel.y = 0
            sprite.hit_rect.centery = sprite.pos.y
            go_to_place(game, destination)
    # todo: same for x!
    if direction == 'x':
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            if hits(0).rect.centerx > sprite.hit_rect.centerx:
                sprite.pos.x = hits(0).rect.left - sprite.hit_rect.width / 2
            if hits(0).rect.centerx < sprite.hit_rect.centerx:
                sprite.pos.x = hits(0).rect.right + sprite.hit_rect.width / 2
            sprite.vel.x = 0
            sprite.hit_rect.centerx = sprite.pos.x
            go_to_place(game, destination)

def go_to_place(game, destination):
    # portal thingy
    game.new(destination)

class Player(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self._layer = PLAYER_LAYER
        self.groups = game.all_sprites
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.player_img
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.hit_rect = PLAYER_HIT_RECT
        self.hit_rect.center = self.rect.center
        self.vel = vec(0, 0)
        self.pos = vec(x, y)
        self.rot = 0
        self.last_shot = 0
        self.health = PLAYER_HEALTH
        self.weapon = 'pistol'
        self.damaged = False

    def get_keys(self):
        # self.rot_speed = 0
        # self.vel = vec(0, 0)
        # keys = pg.key.get_pressed()
        # if keys(pg.K_LEFT) or keys(pg.K_a):
        #     self.rot_speed = PLAYER_ROT_SPEED
        # if keys(pg.K_RIGHT) or keys(pg.K_d):
        #     self.rot_speed = -PLAYER_ROT_SPEED
        # if keys(pg.K_UP) or keys(pg.K_w):
        #     self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)
        # if keys(pg.K_DOWN) or keys(pg.K_s):
        #     self.vel = vec(-PLAYER_SPEED / 2, 0).rotate(-self.rot)
        # if keys(pg.K_SPACE):
        #     self.shoot()
        self.vel = vec(0, 0)
        keys = pg.key.get_pressed()
        if keys(pg.K_LEFT) or keys(pg.K_a):
            self.vel = vec(-PLAYER_SPEED, 0)
        if keys(pg.K_RIGHT) or keys(pg.K_d):
            self.vel = vec(PLAYER_SPEED, 0)
        if keys(pg.K_UP) or keys(pg.K_w):
            self.vel = vec(0, -PLAYER_SPEED)
        if keys(pg.K_DOWN) or keys(pg.K_s):
            self.vel = vec(0, PLAYER_SPEED)
        if keys(pg.K_SPACE):
            self.shoot()

    def shoot(self):
        now = pg.time.get_ticks()
        if now - self.last_shot > WEAPONS(self.weapon)('rate'):
            self.last_shot = now
            dir = vec(1, 0).rotate(-self.rot)
            pos = self.pos + BARREL_OFFSET.rotate(-self.rot)
            self.vel = vec(-WEAPONS(self.weapon)('kickback'), 0).rotate(-self.rot)
            for i in range(WEAPONS(self.weapon)('bullet_count')):
                spread = uniform(-WEAPONS(self.weapon)('spread'), WEAPONS(self.weapon)('spread'))
                Bullet(self.game, pos, dir.rotate(spread), WEAPONS(self.weapon)('damage'))
                snd = choice(self.game.weapon_sounds(self.weapon))
                if snd.get_num_channels() > 2:
                    snd.stop()
                snd.play()

    def hit(self):
        self.damaged = True
        self.damage_alpha = chain(DAMAGE_ALPHA * 4)

    def update(self):
        self.get_keys()
        self.image = self.game.player_img
        if self.damaged:
            try:
                self.image.fill((255, 255, 255, next(self.damage_alpha)), special_flags=pg.BLEND_RGBA_MULT)
            except:
                self.damaged = False
        self.rect = self.image.get_rect()
        self.rect.center = self.pos
        self.pos += self.vel * self.game.dt
        self.hit_rect.centerx = self.pos.x
        collide_with_walls(self, self.game.walls, 'x')
        collide_with_portal(self.game, 'eg.dungeon.tmx', self, self.game.portals, 'x')
        self.hit_rect.centery = self.pos.y
        collide_with_walls(self, self.game.walls, 'y')
        collide_with_portal(self.game, 'eg.dungeon.tmx', self, self.game.portals, 'y')
        self.rect.center = self.hit_rect.center

    def add_health(self, amount):
        self.health += amount
        if self.health > PLAYER_HEALTH:
            self.health = PLAYER_HEALTH

class Mob(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self._layer = MOB_LAYER
        self.groups = game.all_sprites, game.mobs
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.mob_img.copy()
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.hit_rect = MOB_HIT_RECT.copy()
        self.hit_rect.center = self.rect.center
        self.pos = vec(x, y)
        self.vel = vec(0, 0)
        self.acc = vec(0, 0)
        self.rect.center = self.pos
        self.rot = 0
        self.health = MOB_HEALTH
        self.speed = choice(MOB_SPEEDS)
        self.target = game.player

    def avoid_mobs(self):
        for mob in self.game.mobs:
            if mob != self:
                dist = self.pos - mob.pos
                if 0 < dist.length() < AVOID_RADIUS:
                    self.acc += dist.normalize()

    def update(self):
        target_dist = self.target.pos - self.pos
        if target_dist.length_squared() < DETECT_RADIUS**2:
            if random() < 0.002:
                choice(self.game.zombie_moan_sounds).play()
            self.rot = target_dist.angle_to(vec(1, 0))
            self.image = pg.transform.rotate(self.game.mob_img, self.rot)
            self.rect.center = self.pos
            self.acc = vec(1, 0).rotate(-self.rot)
            self.avoid_mobs()
            self.acc.scale_to_length(self.speed)
            self.acc += self.vel * -1
            self.vel += self.acc * self.game.dt
            self.pos += self.vel * self.game.dt + 0.5 * self.acc * self.game.dt ** 2
            self.hit_rect.centerx = self.pos.x
            collide_with_walls(self, self.game.walls, 'x')
            self.hit_rect.centery = self.pos.y
            collide_with_walls(self, self.game.walls, 'y')
            self.rect.center = self.hit_rect.center
        if self.health <= 0:
            choice(self.game.zombie_hit_sounds).play()
            self.kill()
            self.game.map_img.blit(self.game.splat, self.pos - vec(32, 32))

    def draw_health(self):
        if self.health > 60:
            col = GREEN
        elif self.health > 30:
            col = YELLOW
        else:
            col = RED
        width = int(self.rect.width * self.health / MOB_HEALTH)
        self.health_bar = pg.Rect(0, 0, width, 7)
        if self.health < MOB_HEALTH:
            pg.draw.rect(self.image, col, self.health_bar)

class Bullet(pg.sprite.Sprite):
    def __init__(self, game, pos, dir, damage):
        self._layer = BULLET_LAYER
        self.groups = game.all_sprites, game.bullets
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.bullet_images(WEAPONS(game.player.weapon)('bullet_size'))
        self.rect = self.image.get_rect()
        self.hit_rect = self.rect
        self.pos = vec(pos)
        self.rect.center = pos
        #spread = uniform(-GUN_SPREAD, GUN_SPREAD)
        self.vel = dir * WEAPONS(game.player.weapon)('bullet_speed') * uniform(0.9, 1.1)
        self.spawn_time = pg.time.get_ticks()
        self.damage = damage

    def update(self):
        self.pos += self.vel * self.game.dt
        self.rect.center = self.pos
        if pg.sprite.spritecollideany(self, self.game.walls):
            self.kill()
        if pg.time.get_ticks() - self.spawn_time > WEAPONS(self.game.player.weapon)('bullet_lifetime'):
            self.kill()

class Obstacle(pg.sprite.Sprite):
    def __init__(self, game, x, y, w, h):
        self.groups = game.walls
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.rect = pg.Rect(x, y, w, h)
        self.hit_rect = self.rect
        self.x = x
        self.y = y
        self.rect.x = x
        self.rect.y = y


class Item(pg.sprite.Sprite):
    def __init__(self, game, pos, type):
        self._layer = ITEMS_LAYER
        self.groups = game.all_sprites, game.items
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.item_images(type)
        self.rect = self.image.get_rect()
        self.type = type
        self.pos = pos
        self.rect.center = pos
        self.tween = tween.easeInOutSine
        self.step = 0
        self.dir = 1

    def update(self):
        # bobbing motion
        offset = BOB_RANGE * (self.tween(self.step / BOB_RANGE) - 0.5)
        self.rect.centery = self.pos.y + offset * self.dir
        self.step += BOB_SPEED
        if self.step > BOB_RANGE:
            self.step = 0
            self.dir *= -1

class Portal(pg.sprite.Sprite):
    def __init__(self, game, x, y, w, h, where):
        self.destination = where
        self._layer = ITEMS_LAYER
        self.groups = game.portals
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.rect = pg.Rect(x, y, w, h)
        self.hit_rect = self.rect
        self.x = x
        self.y = y
        self.rect.x = x
        self.rect.y = y
        g.new('overworld.tmx')
        g.run()

tilemap.py

import pygame as pg
import pytmx
from settings import *

def collide_hit_rect(one, two):
    return one.hit_rect.colliderect(two.rect)

class Map:
    def __init__(self, filename):
        self.data = ()
        with open(filename, 'rt') as f:
            for line in f:
                self.data.append(line.strip())

        self.tilewidth = len(self.data(0))
        self.tileheight = len(self.data)
        self.width = self.tilewidth * TILESIZE
        self.height = self.tileheight * TILESIZE

class TiledMap:
    def __init__(self, filename):
        tm = pytmx.load_pygame(filename, pixelalpha=True)
        self.width = tm.width * tm.tilewidth
        self.height = tm.height * tm.tileheight
        self.tmxdata = tm

    def render(self, surface):
        ti = self.tmxdata.get_tile_image_by_gid
        for layer in self.tmxdata.visible_layers:
            if isinstance(layer, pytmx.TiledTileLayer):
                for x, y, gid, in layer:
                    tile = ti(gid)
                    if tile:
                        surface.blit(tile, (x * self.tmxdata.tilewidth,
                                            y * self.tmxdata.tileheight))

    def make_map(self):
        temp_surface = pg.Surface((self.width, self.height))
        self.render(temp_surface)
        return temp_surface

class Camera:
    def __init__(self, width, height):
        self.camera = pg.Rect(0, 0, width, height)
        self.width = width
        self.height = height

    def apply(self, entity):
        return entity.rect.move(self.camera.topleft)

    def apply_rect(self, rect):
        return rect.move(self.camera.topleft)

    def update(self, target):
        x = -target.rect.centerx + int(WIDTH / 2)
        y = -target.rect.centery + int(HEIGHT / 2)

        # limit scrolling to map size
        x = min(0, x)  # left
        y = min(0, y)  # top
        x = max(-(self.width - WIDTH), x)  # right
        y = max(-(self.height - HEIGHT), y)  # bottom
        self.camera = pg.Rect(x, y, self.width, self.height)

settings.py

import pygame as pg
vec = pg.math.Vector2

# define some colors (R, G, B)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
DARKGREY = (40, 40, 40)
LIGHTGREY = (100, 100, 100)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BROWN = (106, 55, 5)
CYAN = (0, 255, 255)

# game settings
WIDTH = 1024   # 16 * 64 or 32 * 32 or 64 * 16
HEIGHT = 768  # 16 * 48 or 32 * 24 or 64 * 12
FPS = 60
TITLE = "some rpg"
BGCOLOR = BROWN

TILESIZE = 64
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE

# Player settings
PLAYER_HEALTH = 100
PLAYER_SPEED = 280
PLAYER_ROT_SPEED = 200
PLAYER_IMG = 'dir_down_fmale.png'
PLAYER_HIT_RECT = pg.Rect(0, 0, 35, 35)
BARREL_OFFSET = vec(30, 10)

# Weapon settings
BULLET_IMG = 'stone spear2.png'
WEAPONS = {}
WEAPONS('pistol') = {'bullet_speed': 500,
                     'bullet_lifetime': 1000,
                     'rate': 250,
                     'kickback': 200,
                     'spread': 5,
                     'damage': 10,
                     'bullet_size': 'lg',
                     'bullet_count': 1}
WEAPONS('shotgun') = {'bullet_speed': 400,
                      'bullet_lifetime': 500,
                      'rate': 900,
                      'kickback': 300,
                      'spread': 20,
                      'damage': 5,
                      'bullet_size': 'sm',
                      'bullet_count': 12}

# Mob settings
MOB_IMG = 'Enemy 06-1.png'
MOB_SPEEDS = (150, 100, 75, 125)
MOB_HIT_RECT = pg.Rect(0, 0, 30, 30)
MOB_HEALTH = 100
MOB_DAMAGE = 10
MOB_KNOCKBACK = 20
AVOID_RADIUS = 50
DETECT_RADIUS = 400

# Effects
MUZZLE_FLASHES = ('whitePuff15.png', 'whitePuff16.png', 'whitePuff17.png',
                  'whitePuff18.png')
SPLAT = 'splat.png'
FLASH_DURATION = 50
DAMAGE_ALPHA = (i for i in range(0, 255, 55))
LIGHT_RADIUS = (500, 500)
LIGHT_MASK = "light_350_soft.png"

# Layers
WALL_LAYER = 1
PLAYER_LAYER = 2
BULLET_LAYER = 3
MOB_LAYER = 2
EFFECTS_LAYER = 4
ITEMS_LAYER = 1
PORTAL_LAYER = 1

# Items
ITEM_IMAGES = {'health': 'Icon3.png',
               'shotgun': 'Icon5.png'}
HEALTH_PACK_AMOUNT = 20
BOB_RANGE = 10
BOB_SPEED = 0.3

# Sounds
BG_MUSIC = 'espionage.ogg'
PLAYER_HIT_SOUNDS = ('pain/8.wav', 'pain/9.wav', 'pain/10.wav', 'pain/11.wav')
ZOMBIE_MOAN_SOUNDS = ('brains2.wav', 'brains3.wav', 'zombie-roar-1.wav', 'zombie-roar-2.wav',
                      'zombie-roar-3.wav', 'zombie-roar-5.wav', 'zombie-roar-6.wav', 'zombie-roar-7.wav')
ZOMBIE_HIT_SOUNDS = ('splat-15.wav')
WEAPON_SOUNDS = {'pistol': ('pistol.wav'),
                 'shotgun': ('shotgun.wav')}
EFFECTS_SOUNDS = {'level_start': 'level_start.wav',
                  'health_up': 'health_pack.wav',
                  'gun_pickup': 'gun_pickup.wav'}

vlc media player – MS Teams calls suspends my RTSP stream open in VLC — How can I resolve this?

I have a Reolink IP cam on my front door that I keep open on a small window so I can see when I have visitors (I can’t hear my doorbell from my office). I’m not interested in recording, only being able to view the front door. I access the feed by launching teams with this argument

vlc.exe rtsp://<username>:<password>@<camera IP>:554//h264Preview_01_main

Every time I initiate a call through MS Teams, the stream gets suspended. There is no visual indicator from VLC or error message, I just notice that the timestamp on the feed stops ticking away and I near longer hear outdoor noises. What’s even weirder is that as soon as I close the teams call, the timer starts advancing again, but with a lag of however long I was in the teams call; so If I was in a call for 15 minutes, my video stream resumes but at fifteen minutes in the past.

What is the cause of the interference, and how can I look to resolve it?

rigidbody – Momentum-wise accurate player controls in Unity regarding collisions

rigidbody – Momentum-wise accurate player controls in Unity regarding collisions – Game Development Stack Exchange

trippable music player desktop-app – User Experience Stack Exchange

I have been interested in the visual operation of systems and programmes for a long time and am just starting to discover this forum. So first of all, a friendly hello!

I love my music collection. I am constantly looking for the perfect oranisation type for my library. Since I mainly like to collect and sort music to enjoy with friends while tripping, I’m facing a problem:
No matter how well I sort my music, it’s worthless if I can’t navigate through it during a trip.

So I’m looking for a UX and UI that is easy enough to use in such a state. On our last trip I gave up trying to find my way around and we played the whole library on shuffle and interacted with MusicBee (the program I use to manage my music library) only via “like” and “next”.

That’s why I had the idea to design a music player just for this kind of application and to implement it with “electron”.

I imagine a cover wall with optional lines or columns of playlists – similar to train-tracks. It should now be possible to “jump” effortlessly from one playlist to another without interrupting the current music playback.
I think the easiest way to controll this, would be with an Xbox One controller. It feels good in the hand, and if you use the buttons intuitively and thoughtfully, it’s more comfortable than any remote control, mouse or keyboard. for example, you could always have to press two active buttons to trigger an action (next, like, etc.) to avoid unintentional gripp”mistakes”.

https://ibb.co/6WKHvjY
Web-1920-1
Web-1920-2
Web-1920-2
Menu
https://ibb.co/bdfmph9

now i’m stuck on the question of how the whole thing should look and behave.
Which functions are absolutely necessary and which can or must be dispensed with in order not to make everything too complicated?

Do you have any ideas or suggestions on how to present the whole thing so that it makes sense?
I’ve already thought about carousels instead of a wall, but I don’t yet see a good way of representing the “jumping”. Horizontal shuffle like a rubiks cube?

I’m curious to hear what you have in mind.

DreamProxies - Cheapest USA Elite Private Proxies 100 Private Proxies 200 Private Proxies 400 Private Proxies 1000 Private Proxies 2000 Private Proxies ExtraProxies.com - Buy Cheap Private Proxies Buy 50 Private Proxies Buy 100 Private Proxies Buy 200 Private Proxies Buy 500 Private Proxies Buy 1000 Private Proxies Buy 2000 Private Proxies ProxiesLive Proxies-free.com New Proxy Lists Every Day Proxies123