This is part of a series of articles that go over the steps I’m taking to learn Flash CS3. The project’s goal is to develop an RPG similar to those published by Square in the mid/late 1990’s. (Secret of Mana, Final Fantasy VI, etc..)
So I have my Hero and I have a decent world for him to traverse. But it’s quite lonely for him all by himself. What we need are some good old fashioned Non-Playable Characters or NPCs. Just like mom used to make.
Milestone: Friends & Enemies
User Story: I will see NPCs roam around the world. Some will be hostile, some will be passive.
This actually ended up being an incredibly short milestone as I found my Hero code easily extensible.
Prototype 1:
I made a copy of Hero.as and created a new NPC.as class. Since my NPCs will have similar walk animations, I just used a copy of my Neco movieClip with a Red Box to differentiate them.
The key changes to the NPC class involved removing any keyboard listeners and instead having some variables that acted as though someone was pressing the arrow keys. When moveRight, moveLeft, moveUp, or moveDown were true, the same movement logic that our Hero uses would be enabled.
So then all I needed to do was create a small class that would flip those boolean variables.
My movement “logic” for NPC.as:
private function moveMe(){ if (Math.random()>0.95){ moveRight = Math.round(Math.random()); moveLeft = Math.round(Math.random()); moveUp = Math.round(Math.random()); moveDown = Math.round(Math.random()); } }
Basically the logic is this… every frame, there is a 5% chance our NPC will change direction. Then there is a 50/50 chance that each move boolean will be active.
This creates a nice erratic walking pattern. Just fine for our brainless (err: Special) NPCs.
Prototype 2:
So our previous logic is fine for brainless NPCs, but it certainly wont make for a challenging enemy. So I’ve made a copy of NPC.as and created Enemy.as. I’ll be focusing on improving my moveMe() function.
First we need a target. So when the enemy is created, I pass it a reference of our Hero. This will allow the enemy to constantly track the Hero no matter where he hides. So my basic logic for the enemy will be:
- Check to see if I’m close to the Hero.
- If I’m not, I should move in his direction!
- If I’m close enough, I should attack.
But of course I don’t want the enemy too smart. Bee-lining straight to the hero wouldn’t be exciting. So movement will use the same 5% rule that I used with the NPC. But the chosen direction will be based on worldX and worldY values.
My movement logic for Enemy.as is:
private function moveMe(){ if ((Math.abs(worldX-target.worldX) >50) && (Math.abs(worldY-target.worldY) >50)) { moveLeft=false; moveRight=false; moveUp=false; moveDown=false; attack(); } else{ if (Math.random()>0.95){ if (worldX>target.worldX){ moveLeft=true; } if (worldX<target.worldX){ moveRight=true; } if (worldY>target.worldY){ moveUp=true; } if (worldY<target.worldY){ moveDown=true; } } if (Math.random()>0.95){ moveLeft=false; moveRight=false; moveUp=false; moveDown=false; } } }
Pretty straight-forward stuff.
In the below prototype Green Squares are sprites with the NPC logic, while Red Squares are sprites with the Enemy logic.
So that was a really easy Milestone. I obviously am leveraging a lot of the work I did with the Hero class in the first place. One thing I could have spent more time with was building more logical classes. Hero.as, NPC.as, and Enemy.as all have very very similar functions and duplicate a lot of code. If I was clever I’d build a parent class that all these could extend. Maybe later
Next step – these enemies need teeth.






