This week, enemies learned to see the player and shoot in their general direction, which increased their deadliness by approximately infinity percent.
Perceiving Players
The easy way to check whether a player is visible to enemies is via "ray casting": you start at an enemy and you draw a line to where a player is; if you get to the player without hitting anything along the way, the player is visible to that enemy!
Fortunately the physics engine I'm using has ray-casting built in, so that generated colliders will block rays. Perfect!
Unfortunately, I forgot that I applied an optimization: we only generate colliders for atoms close to the player and to enemies.
You can see it more clearly with some debug output on:
So I swapped to my own custom raycasting, which simply looks at atoms one by one along the path of the line. 1
This variant does have the opposite problem of being able to (always) see through moving bodies, but I think that will be okay gameplay-wise.
Enemy AI
These days, AI is a blanket term for magic sauce that causes people to throw money at your company.
But it wasn't that long ago that the only (non-academic) people seriously interested in AI were game developers.
Yet game AI is less making game entities intelligent and more making them fun (or challenging, or frustrating, or ...). Design the experience, then fake as much as you can.
So, I want enemies to start unaware of the player, and attack the player once they've spotted 'em:
Actually, probably enemies should attack more than just the once, so we'll need a timer to track when they can attack next.
I also want the player to have the satisfaction of running up and using a close-ranged spell if they're fast enough, so enemies should have a brief period of surprise-driven inaction when they first spot the player.
But if the player hides then enemies shouldn't be surprised again if the player pops up immediately; enemies should remember they saw the player recently.
This is what nerds2 call a State Machine.
And here's what it looks like in action:
- The big red/green box is the vision range of the enemy.
- It makes sure that enemies only spot players somewhat close to (and in front of) them.
- When the player enters the red/green box, the enemy raycasts to the player.
- If the raycast hits the player, then the enemy acts surprised.
- Eventually the enemy recovers and shoots at the player every few seconds.
- And when the player hides, the enemy looks around for a while to see where they went.
Obviously the enemy would be rather more effective in searching for the player if they were to, you know, move around a bit - but that's a whole 'nother topic.
(And yes, in this magical world, arrows travel in a straight line unaffected by gravity.)
The First Playtest
Sure, there are online demos here, but this week I attended a couch co-op session, so I had 2-3 peeps play my demo without reading any of my copious words beforehand.
And wow! This first playtest was both impressively embarrassing3 and wonderfully eye opening:
- Some players don't randomly mash buttons on controllers to find out how to play.
- Coal looks like charcoal, and unfortunately so does oil.
- Fire from a distance looks like "wait what's that yellow line that's moving".
- "Respawn by touching the spawn" (or even "what is the spawn point") didn't click straight away.
- It's super jarring to have the level insta-reset when everyone dies or the next level loads in.
- The Mario-style "hold jump to jump higher" mechanic felt too floaty (try it again now! should be better).
- You can't really experience much of the "cool" atom interactions without using a mouse, so even as a tech demo it fell kinda flat.
Thank you to those poor souls. (Also please stop abusing the laser in Bopl Battle!)
Arrow-filled web build
Dodge some goblin arrows here:
For the enemy vision visualization, press F2 and turn on
Enemies >> Show vision
.
And yeah, the enemies don't have attack animations yet - all in due course.
The actual algorithm for stepping pixel-by-pixel is an integer-arithmetic only version of Bresenham's line algorithm. Conveniently I already had it floating around because it's used for some of the water movement logic, and for painting atoms using the paint tool without any gaps when you move the mouse really quickly.
proudly including me.
Other game devs have mentioned that the first play test is always embarrassing, but you don't get it until you're in the hot seat.