Category: Roguelike


Bunch of minor tweaks to the Target selection dialog/process; it’s working for Single-mob targets and most of the code is there for AoE effects, but I have a little ways to go before it’s done.  Here’s what it looks like now:

Of note:

  • I’ve removed the “previous” button – I don’t think it’ll get used.  This leaves the dialog unbalanced; something to fix later (perhaps with an “Info” button that brings up an Info dialog for the selected mob)
  • I’m highlighting out-of-range and invalid selection (e.g. wall) cells in Red.
  • I’ve made a number of tweaks to the selection logic; e.g. tracking the last selected mob, using and updating the ContextualActionBar’s selected mob, etc.

Still todo:

  • I’ve reached the point where I need to be able to inject values into event text messages.  For instance, the text for the Bolt of Light skill will be something akin to “A bolt of light hits {target} for {amount}.”  I need to be able to dynamically replace those {} values; I could pull that out of the Action.Info field, but that gets interesting for Events that have multiple Actions.  Requires more thought…
  • I’ve somehow managed to break the data-driven Animations :).  I’ll get that fixed tonight and do a code drop then.
Advertisements

Currently, Skills can only be used against the “Self” target – e.g. you can cast a Heal spell on yourself, but not on another Actor.  I’m extending Event Targets to include SingleMob, Cell (for Area of Effect skills), and later “Item” (e.g. for identify).  Bunch of random infrastructure for this and some design work.  I’m probably 80% done with the SingleMob target work, and 50% done with AoE.

To demo the UX, I’ve added a new “Bolt of Light” skill which does damage to a SingleMob target.  Here’s what you see when you perform that skill:

One of the challenges with the UX is that I’m trying to support the ability for the user to play the game with minimal finger movement (I don’t want to force them to change how they’re holding the phone every time they use a skill).  Simultaneously, I want them to be able to tap-to-select if so desired.  The above UX should support either model…

I’m hoping to get at least the SingleMob targeting done tonight and will drop some code at that point.

Jeff

This drop includes support for Xml-based particles as part of the Animation system. I’m not 100% happy with the implementation, but particles and animation isn’t where I’m looking to innovate ;-). I am happy with how the Particle animations integrate in with the target and tile animations; particle systems can leverage the same scale and move (and to a lesser extent rotate) transforms that the other Animations types support. This’ll allow more involved animations later when I get around to creating them…

Particle Animations

I adopted and adapted the particle system from the Xml-driven particle sample up on create.msdn.com (here).  The short version:

ParticleEmitter: Emits Particles (surprise!). This manages how often particles are emitted, what direction they’re emitted in, and their starting position.  Multiple forms of emitters are supported: Cone, Circle, and Rectangle.  For Circle and Rectangle emitters, you can define whether particles should originate within the emitter shape or on the edge of the shape.  You can also define whether Particles should radiate outward from the center of the shape or in random directions.

ParticleSystem: Once Particles are emitted by a ParticleEmitter, the ParticleSystem manages them – so things like gravity/wind and ColorShifting or particle Scale Animations are managed by the ParticleSystem.

ParticleMgr: Single instance object that keeps track of all ParticleSystems and ParticleEmitters, keeping them alive and removing them when they’re done.  This is the object with which the main game loops (update/draw) interact.

Defining Particle animations

These are defined in the same fashion as other data-driven animations; via Xml.  Here’s an example of a simple particle animation that emits then in a cone:

  <Animation Id="BlueSparkles-Cone">
    <ParticleAnim Type="Cone" StartTick="0" EndTick="5000" TileId="Bluestar" NumParticlesRange="5,10" Render="UnderTarget"
                     DirAngleRange="45, 90" InitialSpeedRange="120,200"
                     AccelerationMode="EndVelocity" EndVelocity="0" RotSpeedRange="-90, 90" LifetimeRange="1,3" SizeRange=".35,.5">
    </ParticleAnim>
  </Animation>

Since the particles can tie into the transforms, you can do things like have the Cone emitter above rotate as it emits particles by just adding a Rotate animation:

  <Animation Id="BlueSparkles-Cone">
    <ParticleAnim Type="Cone" StartTick="0" EndTick="5000" TileId="Bluestar" NumParticlesRange="5,10" Render="UnderTarget"
                     DirAngleRange="45, 90" InitialSpeedRange="120,200"
                     AccelerationMode="EndVelocity" EndVelocity="0" RotSpeedRange="-90, 90" LifetimeRange="1,3" SizeRange=".35,.5">
      <Rotate StartTick="0" EndTick="5000" StartDegrees="0" DegreesPerSecond="180"/>
    </ParticleAnim>
  </Animation>

Here’s another example of a particle Animation which emits particles in a rectangle shape and applies a colorshift animation to them:

  <Animation Id="FireRect">
    <ParticleAnim Type="Rect" Area="-80, -80, 160, 160" StartTick="0" EndTick="5000" TileId="redglow" NumParticlesRange="15,20" Render="UnderTarget"
                     InitialSpeedRange="0,10" Gravity="0, -300"
                     AccelerationMode="EndVelocity" EndVelocity="0" RotSpeedRange="-90, 90" LifetimeRange="1,1" SizeRange=".5,1.5">
      <ColorShift StartTick="0" EndTick="3000" StartColor="255,255,255" EndColor="0,255,0"/>
      <ColorShift StartTick="3000" EndTick="5000" StartColor="0,255,0" EndColor="255,255,255"/>
    </ParticleAnim>
  </Animation>

And just for fun, here’s a complex animation:

  <Animation Id="BlueTornado">
    <TargetAnim>
      <ColorShift StartTick="0" EndTick="5000" StartColor="0,0,255" EndColor="0,0,255"/>
      <LinkedAnimation RefId="BlueSparkles"/>
    </TargetAnim>
    <ParticleAnim StartTick="0" EndTick="5000" TileId="Bluestar" NumParticlesRange="5,10" Render="UnderTarget"
                   DirAngleRange="0, 359" InitialSpeedRange="120,200"
                   AccelerationMode="EndVelocity" EndVelocity="0" RotSpeedRange="-90, 90" LifetimeRange="1,3" SizeRange=".15,.5"/>
    <TileAnim TileId="RingOfFire2" Render="UnderTarget">
      <ColorShift StartTick="0" EndTick="2500" StartColor="255,255,255" EndColor="0,255,255"/>
      <ColorShift StartTick="2500" EndTick="5000" StartColor="0,255,255" EndColor="0,0,255"/>
      <Rotate StartTick="0" EndTick="2000" StartDegrees="0" DegreesPerSecond="720"/>
      <Scale StartTick="0" EndTick="2000" StartScale="1" EndScale="3"/>
      <Rotate StartTick="2000" EndTick="5000" StartDegrees="0" DegreesPerSecond="360"/>
      <Scale StartTick="2000" EndTick="5000" StartScale="3" EndScale=".1"/>
    </TileAnim>
    <TileAnim TileId="RingOfFire2" Render="UnderTarget">
      <ColorShift StartTick="0" EndTick="2500"  StartColor="0,255,255" EndColor="0,0,255"/>
      <ColorShift StartTick="2500" EndTick="5000"  StartColor="0,0,255" EndColor="0,255,255"/>
      <Scale  StartTick="0" EndTick="5000" StartScale="1" EndScale="1"/>
      <Rotate  StartTick="0" EndTick="5000" StartDegrees="0" DegreesPerSecond="-180"/>
    </TileAnim>
  </Animation>

I’ve created a video that demonstrates what those animations (and others) look like. Note that to demo this I just added a few skills to the Skills.xml file and set each Skill’s SelfAnimation attribute to one of the Animations in Animations.xml:

Updated source: http://wanderlinggames.com/files/dungeon/dungeon-4-12-11.zip

Updated executable: http://wanderlinggames.com/files/dungeon/dungeonexe-4-12-11.zip

I’ve fixed the zooming issue and also implemented easing in and out.  The main thing remaining to add is Particle Animations; those may wait a couple of days as my main goal was to get the data-driven animation infrastructure in place and running.

You can tie an Animation to any Event; in the Xml snippet below, it’s triggered by the “StartResting” Event that’s associated with the “SelfAnimation” field of the Item which the Player is wielding:

    <Weapon Id="Axe1" Name="Rusty Hatchet of Resftul Mapping" Subclass="Axe" WeaponPower="10" ItemLevel="1" Level="1-3"
            Tile="AxeBeaked" Description="A rusty hatchet">
      <Event Type="StartResting" OnFireText="You sense the world around you" SelfAnimation="MoveTest">
        <MagicMapping Amount="1%"/>
      </Event>
    </Weapon>

Here’s a quick video clip of what the Animation from my previous post looks like:

The data-driven Animation classes themselves are straightforward; the only part worth calling out is that I leverage a set of override values (ForcedMoveAmount, ForcedScaleAmount, etc), and instead of a boolean for “ForceMove”, I use a ref-count like model which supports multiple Animations working on the same object at the same time. Here’s the complete code for AnimationKeyFrame_Move; most of it is just determining which easing type to use:

    class AnimationKeyFrame_Move : AnimationKeyFrame
    {
        public AnimationKeyFrame_Move(KeyframeAppliedTo appliedTo, int appliedToTileIndex)
            : base(appliedTo, appliedToTileIndex)
        {
        }
        public override void Render(int timeTick, float percentDone, GameObject performer, GameObject target)
        {
            switch (Easing)
            {
                case Easing.EaseOut:
                    performer.ForcedMoveAmount += (EndLoc - StartLoc) * percentDone * percentDone + StartLoc;
                    break;

                case Easing.EaseIn:
                    performer.ForcedMoveAmount += (StartLoc - EndLoc) * (1 - percentDone) * (1 - percentDone) + EndLoc;
                    break;

                case Easing.Linear:
                    performer.ForcedMoveAmount += StartLoc + (EndLoc - StartLoc) * percentDone;
                    break;
            }
        }

        public override void Start(GameObject performer, GameObject target)
        {
            // We're within the keyframe's slot - force a move.  Do this as a 'refcount' to
            // support multiple simultaneous animations
            performer.ForceMove++;
        }

        public override void End(GameObject performer, GameObject target)
        {
            performer.ForceMove--;
        }

        public Vector2 EndLoc;
        public Vector2 StartLoc;
    }

One bit of hackery to eventually replace is that I’ve modified the render loop to run as a series of render phases; this allows Animations to specify whether they should render on top of or underneath objects; it also ensures that tiles don’t draw over objects when the objects scale or move. I believe I can actually do away with the entire multipass approach and just leverage the depthbuffer using pre-defined depth values. For instance, if all tiles rendered at depth 1, and all objects rendered at depth .5, then an Animation can simply be rendered at .75 or .25 depending on whether it should appear under or over objects…

An interesting question that this raises: what happens if the user moves while a long animation is playing?  What if they perform the same Animation-generating Action multiple times in quick succession? Should the animation stop (jarring)?  Should the user not be allowed to move while animations are playing (forces slow gameplay)?  Should all animations be required to be short (limiting)?  I’m honestly not sure…  I ran into the same issue with the floating combat text – if the user attacks a bunch of times in succession then they get overlapping text.  I’m… not sure what the right answer is here yet.

Updated source: http://wanderlinggames.com/files/dungeon/dungeon-4-11-11.zip

Updated executable: http://wanderlinggames.com/files/dungeon/dungeonexe-4-11-11.zip

I’m adding the ability to create Animations that are applied when Events fire (e.g. Skill used, Trap triggered, ItemEvent fired, etc). This is mostly done, with some tweaks to zoom handling still needed. It’s built around a basic keyframe model, and currently supports;

  • Scale, Move, and Rotate animations.
  • ColorShift animations
  • All Animations can be applied to either the Target (e.g. the Player) or can specify a Tile image to display and animate
  • LinkedAnimations. This’ll come in handy for most complex animations later
  • Both performer and target animations; e.g. if an Event fires on KilledActor, you can specify separate Animations to apply to both the killer and the victim.

Here’s an example of an Animation that smoothly color shifts to green and back again over 2 seconds.

  <Animation Id="GreenTint">
    <TargetAnim>
      <ColorShift StartTick="0" EndTick="1000" StartColor="255,255,255" EndColor="0,255,0" Easing="Linear"/>
      <ColorShift StartTick="1000" EndTick="2000" StartColor="0,255,0" EndColor="255,255,255" Easing="Linear"/>
    </TargetAnim>
  </Animation>

And here’s a much more complex animation that leverages all of the supported features:

  <Animation Id="MoveTest">
    <TargetAnim>
      <LinkedAnimation RefId="RedToGreenRotate"/>
      <Scale StartTick="0" EndTick="1000" StartScale="1" EndScale="4"/>
      <Scale StartTick="1000" EndTick="5000" StartScale="4" EndScale="1"/>
    </TargetAnim>
    <TileAnim TileId="RingOfFire" Render="UnderTarget">
      <ColorShift StartTick="0" EndTick="2500" StartColor="255,255,255,128" EndColor="255,255,255,255" Easing="Linear"/>
      <ColorShift StartTick="2500" EndTick="5000"  StartColor="255,255,255,255" EndColor="255,255,255,128" Easing="Linear"/>
      <Rotate StartTick="0" EndTick="2000" StartDegrees="0" DegreesPerSecond="720"/>
      <Scale StartTick="0" EndTick="2000" StartScale="1" EndScale="3"/>
      <Rotate StartTick="2000" EndTick="5000" StartDegrees="0" DegreesPerSecond="360"/>
      <Scale StartTick="2000" EndTick="5000" StartScale="3" EndScale=".5"/>
    </TileAnim>
    <TileAnim TileId="RingOfFire" Render="UnderTarget">
      <LinkedAnimation RefId="ShakingSparkles"/>
      <ColorShift StartTick="0" EndTick="5000"  StartColor="00,255,255" EndColor="0,255,255" Easing="Linear"/>
      <Scale  StartTick="0" EndTick="5000" StartScale="1" EndScale="1"/>
      <Rotate  StartTick="0" EndTick="5000" StartDegrees="0" DegreesPerSecond="-180"/>
    </TileAnim>
  </Animation>

Here’s what the animation above looks like part-way through:

With this I can create some pretty complex animations, but I’d still like to add:

  • Particle animation support
  • Basic easing in and out.

Code drop tomorrow after I get the zoom handling fixed in Animations.

I’ve uploaded a new work in progress video to YouTube.  This briefly showcases much of the infrastructure that’s been added in the last couple of weeks, including:

* Items
* Weapons and wield/unwield
* Attack sequence
* Zooming
* Event/Action system rewrite
* ContextualActionBar
* SkillBar
* Player Skills
* Monster Skills
* Skill Selector

The Skill Selector dialog is now coded up.  In addition to what I mentioned below, it supports more skills by scrolling the list (but that won’t be obvious until I get a few more skills into there 🙂 ).

Yesterday’s post talked to most of this, so just a code drop today.  I’ll likely pull together a new WiP tomorrow ’cause there’s lots of new stuff since the last one…

Updated source: http://wanderlinggames.com/files/dungeon/dungeon-4-9-11.zip

Updated executable: http://wanderlinggames.com/files/dungeon/dungeonexe-4-9-11.zip

I’m almost done with the Mahjong badges stuff (and am hoping to complete that tomorrow morning), but I was still able to make a bit of progress here as well.

What I’ve been working on is the “Skill Selector,”  which is a dialog that pops up when you click the UseSkill button.  This dialog shows all of the Skills available to the Player and lets you perform them.

Additionally, the Player can drag skills from the Skill Selector down into the Skill Bar for later use (analogous to dragging a skill in WoW from your spellbook to a bar).

This required adding a new Dialog infrastructure, but that’ll come in useful later as well.

This is 90% working, just need to close down on a few bugs tomorrow…

Code drop tomorrow!

Cheers,

Jeff

Day 28: Sneak peek

I’m a bit distracted by work on the Mahjong Badge stuff, but I still managed to make some good progress on the next big feature.  It’s not ready for prime-time, but here’s a sneak peek:

Small update today, but a good one – Skills are now persisting for both Player and Monster Skills.  This was easy to add to the Player class, but required a little refactoring with Monsters.  I also took the opportunity to convert Skill.GetSkillById from an enumeration of a List of Skills to a faster Dictionary lookup.

Separately, I’m working through how I might add “Badges” to my Mahjong game.  I’ve got a score service set up (running against my own server hosted up on <shame>GoDaddy</shame>) so a lot of the hard part’s done.  That’s applicable here because I’m certainly interested in bringing global high scores/stats and Badges to my roguelike as well!

Updated source: http://wanderlinggames.com/files/dungeon/dungeon-4-6-11.zip

Updated executable: http://wanderlinggames.com/files/dungeon/dungeonexe-4-6-11.zip