Skip to content
Tags

89. 3D FPS – Wraiths in the mist

July 7, 2013

Having figured out how to touch objects on a 3D screen (post #70a), and having a misty hillside (post #79), I’m going to add some wraiths that will chase me around and kill me, unless I kill them first.

I’ll share the code, but because it inevitably gets complex and hard to explain (without getting really boring), I’ll pick out what I’ve added to my previous work. I’m going to refer to previous posts a lot, so you know where I explained things.

So what I want to do is

  • have a lost and lonely hillside covered in mist – already done
  • add some scary characters
  • animate those characters so they don’t look wooden
  • have them chase me if I get close
  • kill them if I touch them
  • have them kill me if they get close for too long
  • show my status (score and health) on screen

and that is pretty close to a first person shooter game.

Animating characters with a tileset

I looked around for a good set of animated 2D images. I don’t need to try to create 3D images (which is pretty much impossible in Codea anyway because of complexity and performance issues) because I can cheat by always rotating my 2D images so they face us (post #63).

Not being a good artist, I’m going to see what I can find on the internet. And I found some nice sets here, and chose this image. I can use it for non commercial purposes, which is fine.

This image has four rows of animations. The top row is the wraith floating, maybe moving about a bit. The next row is the same, from behind. The third row is the wraith attacking (front and back view), and the fourth shows it dying.

Now I need to chop up this large image into four different parts, one for each row, and split out each frame, so I can draw them in succession to get the animation effect. The way I did this was to

  1. open the image in a paint program (I use Paint.Net (free) on Windows), and hover the mouse over the gaps between the images so the program would tell me the pixel positions for each frame, and write these down (unfortunately, they weren’t evenly spaced). Now because my Windows program counts y values from the top down, and Codea works from the bottom up, I had to subtract the Windows values from the image size to get the value for Codea (thank you, Excel).

  2. write a simple Codea program that used these pixel positions to copy part of the main image and show it on screen, one frame after another, slow enough that I could see how well the frames overlapped. The first time, all the frames jumped around because I wasn’t starting in the right place, or I cut the wraith’s head off, and I had to tweak the pixel positions until each of the four animations (hover forwards, hover looking away, attack, die) looked smooth.

  3. convert all the pixel positions to fractions of total image width (or height), because I will be drawing them using meshes and AddRect, and setting the image texture with setRectTex. The values you give setRectTex have to be the fraction of width or height, so if for example, your frame starts at x=400,y=300 of an image with width=1000, height=2000, then you need x=0.4, y=0.15 for setRectTex. (Excel to the rescue here again).

Here is the eventual data for my animations. There are several “Left” values because the frames run from left to right in the tileset image.

--four rows below: 1=facing toward,2=facing away,3=attack,4=dying
anim={{Bottom=.815,Height=.199,Width=.103,
          Left={.004,.111,.222,.339,.455,.582,.704,.817}},
      {Bottom=.604,Height=.199,Width=.103,
          Left={.004,.114,.225,.341,.458,.580,.704,.817}},
      {Bottom=.369,Height=.199,Width=.103,
          Left={.222,.354,.222,.354,.004,.111,.222,.354}},
      {Bottom=.128,Height=.199,Width=.103,
          Left={.004,.111,.222,.339}}}
  1. decide how frequently to change frames. I chose to go to the next animation frame after every 10 redraws, which looked about right when I ran it. My program already has a counter count that adds 1 on every redraw, so I can check whether it is time to change frames by using Lua’s mod function (post #46). The code below changes frames every charFrameSpeed draws, starting with the very first draw.
    if count%charFrameSpeed==1 then
        --go to next frame, wrap back to first frame
        -- if we are at the end
    end
  1. switch between actions (eg from hovering to attacking). More on this below, but for now, all I need to do is ensure I can switch smoothly from one to the other, if I want to.

  2. run the death animation after I hit a wraith. This adds some complexity, because unlike the other animations, it only runs once and then the character disappears, so I need a little extra code to manage this.

Navigation

Previously, I’ve used screen touches to navigate, ie steer and walk. But now I want to touch the bad guys to kill them, so I need another way of steering and moving. So I followed the typical approach of creating an onscreen touchpad, as shown below (I don’t like using them, but is there another way?).
http://instagram.com/p/bdMiobBHa9/
The touchpad has four sections. The left and right sections turn my character, and the top and bottom sections move forward and back. The character keeps moving, so you don’t need to keep pressing. The little circle in the middle stops the character.

This looks really simple, but it probably took me 3 hours of messing around to come up with this, including figuring out the trigonometry of drawing all the lines and identifying which section has been touched. I never was good at trigonometry, and I always have to google what I need.

The killer touch

Now I want to be able to touch the bad guys to kill them. I know how to identify touched objects on a 3D screen (post #70a), so when I add my wraiths to the map, I give each of them an id number that can be used to track them, which is kept in a table along with their mesh. When I touch them, I identify which one was touched and delete it from the table of meshes, so it disappears.

The chase

Now I want the wraiths to see me and chase me if I get close enough. I’m not about to write a complex AI personality for these guys. The simplest approach I can think of is that if I come within (say) 100 pixels of them, they run after me and try to kill me, doing their scary attack animation.

It’s easy to check the distance using the dist function provided in Codea, but how do I move them? If you want the wraith to move (say) 1 pixel per draw, the exact change in x and z will depend on the angle of movement, but there is an easy way to do it with having to google trigonometry yet again, like this:

  1. we’ve just calculated the distance to the wraith, say d
  2. we know the difference in x value and y value between us and the wraith, say dx and dy
  3. we want to move m pixels

so let’s do x first. We know that x changes by dx over the distance d, so if we move m pixels, x will change by dx*m/d. So we can pro rate to get the change in x, and then do the same for y.

Bits and pieces

I’ve kept the rest of it quite simple. You kill wraiths with one shot, increasing your score. Wraiths damage your health if they get close, and if that happens I add a pink filter over the screen rather like the red mist you see in many FPS games.

I haven’t worried about winning and losing messages, or respawning. My main objective is not to make a polished game, but to develop tools to allow games like this. And I think I got close enough.

The shader

For those who are interested, the shader used in this program actually does three different things. The vertex shader handles the mist effect, while the fragment shader discards transparent pixels and also helps identify touched objects, as explained in my post #70a. I have covered all of these previous posts.

The code

The code is here. One warning – Codea may be unresponsive when you run it the first time, because there seems to be some kind of problem with images that are freshly downloaded. You may have to stop the program and rerun it, or even restart Codea. I apologise for that, but there is currently no workaround. Failing everything else, the three images needed for this program are listed near the bottom of Main – you will see the Dropbox names and the URLs, so if you prefer, you can manually copy the images into your Dropbox folders with the names shown, and it should work..

I guess you can see that writing 3D games takes a lot of time and effort! This not very complicated 3D game requires drawing (and walking over rather than through) 3D terrain, managing 2D objects in a 3D world, sorting objects so they are drawn furthest to nearest, a mist effect, identifying which object was touched, deleting transparent pixels, and animated characters.

Advertisement

From → 3D, animation, Games

2 Comments
  1. Saurabh permalink

    Maybe you could use the hand gestures to hit and the on screen touches to move around. That would make it classy if it would be possible to make the gestures accurate

    • Lol, that would be a real combination of everything I’ve blogged about! Let’s get this done first….

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: