DEV Community

Cover image for I Built a Pixel Art Village Where AI Characters Have Real Emotions
devjiro
devjiro

Posted on

I Built a Pixel Art Village Where AI Characters Have Real Emotions

Last weekend I fell into a rabbit hole: what if game characters didn't just have scripted reactions, but actually felt things?

Not "if health < 20 then scared" kind of feelings. Something more like: a brooding introvert who slowly warms up to someone who keeps being kind, but snaps hard when betrayed. A resilient gym coach who barely flinches at insults. A shy librarian who experiences the deepest joy from simple affection.

So I built Persona World -- a pixel art village where 12 AI characters live, wander, interact, and develop real emotional states.

What It Looks Like

Village overview with 12 characters wandering around

Each character walks around the village, and when they meet, they autonomously decide what to do -- based on their personality. You can see their current emotion floating above their head.

Character detail panel showing emotional state and relationships

Click on any character to inspect their inner world: their VAD (Valence-Arousal-Dominance) emotional state, personality traits, and how they feel about every other character.

How Emotions Work

Each character has a HEXACO personality profile -- six dimensions that shape how they respond to everything:

  • Openness -- creative vs. conventional
  • Conscientiousness -- disciplined vs. spontaneous
  • Extraversion -- outgoing vs. reserved
  • Agreeableness -- cooperative vs. competitive
  • Neuroticism -- sensitive vs. calm
  • Honesty-Humility -- sincere vs. pragmatic

When an interaction happens (praise, tease, betray, etc.), an emotion engine computes the character's response using a 9-dimensional cognitive appraisal model. The result isn't a simple label -- it's a continuous emotional state in VAD space that shifts based on personality, current mood, and history.

For example, "Nyx" -- an introverted, sensitive poet (N=0.85, E=0.15) -- reacts to betrayal with the most intense emotional response in the entire village. Meanwhile "Rex" -- a resilient extraverted coach (E=0.95, N=0.25) -- barely registers the same event.

The Interesting Part

What surprised me was watching the emergent dynamics:

Personality shapes everything. The same action produces wildly different results depending on who receives it. "Affection" makes Nyx feel genuine joy (she rarely gets positive attention) but barely moves Miko (who's already emotionally stable).

Relationships accumulate. Characters track how others have treated them. Over time, a character who receives mostly positive actions from someone will start preferring positive actions back. Negative spirals happen too.

Mood is slow, emotion is fast. A single insult doesn't ruin a character's day. But sustained negativity gradually shifts their baseline mood, which colors all future reactions.

Tech Stack

  • Frontend: React 19 + Canvas 2D + TypeScript
  • Emotion Engine: molroo SDK -- handles personality modeling, cognitive appraisal, and VAD emotion computation
  • Rendering: Pixel art sprites on HTML Canvas
  • Hosting: Cloudflare Pages

The emotion engine does the heavy lifting. Each interact() call sends an action with a 9-dimensional appraisal vector, and returns the character's new emotional state -- including discrete emotion labels, VAD values, mood shifts, and even somatic responses (physical sensations like "chest tightness" or "warm glow").

Try It / Build Your Own

Live demo: persona-world.pages.dev

Source code: github.com/devjiro76/persona-world

The whole thing is open source. You can swap out the 12 characters with your own (just edit src/data/personas.ts), change their personalities, or add new interaction types.

To run it yourself, you just need an API key:

git clone https://github.com/devjiro76/persona-world.git
cd persona-world
npm install
cp .env.example .env  # add your API key
npm run dev
Enter fullscreen mode Exit fullscreen mode

The app auto-creates a world and seeds all 12 characters on first run.


I'm curious -- has anyone else experimented with continuous emotion models in games or simulations? Most AI character systems I've seen use discrete states or simple sentiment. The VAD approach feels more natural but I'm still finding edge cases (surprise is nearly impossible to trigger, and "challenge" produces numbness instead of determination).

Would love to hear thoughts or ideas.

Top comments (2)

Collapse
 
klement_gunndu profile image
klement Gunndu

Using HEXACO over Big Five is a smart call for character simulation — the Honesty-Humility axis alone opens up betrayal dynamics that Big Five can't model. Curious if the VAD state decays over time or stays persistent.

Collapse
 
miss_terry profile image
devjiro

Thanks! HEXACO's H axis is exactly why we chose it — trust/betrayal, deception, fairness dynamics all come naturally from Honesty-Humility without needing ad-hoc flags.

On VAD decay: yes, it decays over time. The engine uses a critically damped oscillator (ζ=1) to return emotion to a personality-derived baseline. So after an interaction, VAD smoothly and monotonically decays back — no ringing or oscillation during idle. The decay rate is governed by a per-persona natural_freq parameter, so neurotic characters return to baseline slower than emotionally stable ones.

Body budget (energy) also recovers during idle, and SDT need (autonomy/competence/relatedness) regress toward equilibrium. So the whole state is dynamic, not persistent.