LiveCode Experiment: 3D Raycasting

Posted by Scott McDonald

This week instead of a game, the result of an experiment with LiveCode. This is not a polished program. As an exercise in optimising with LiveCode, I set myself the challenge of developing a 3D raycasting demo using only the LiveCode engine. This means no externals (like Franklin 3D) or a library written in another language more suited to 3D games.

Before you alert me of the fact that pure LiveCode is not the best platform to choose when developing 3D games, this I know. As stated above, this is an experiment in finding ways of optimising the speed of graphics and code in LiveCode. In the process, if I can have fun by creating the bare bones of an early 1990s first person game, why not?

The result of this experiment is LiveCode Spider Hunt. The concept puts you in a small building infested with overgrown spiders. Your goal is to kill all the spiders and to find the exit point. You have a can of bug spray. To keep track of how you are going, the status shows the number of dead spiders out of a total, and the distance to your goal.

In addition to this information, Spider Hunt shows the average frames per second (fps), and the average time in milliseconds (ms) required to update each frame. This status is updated every five seconds so this calculation does not affect the frame rate.

In the executable you will see in action:

  • A 3D representation of a room created with LiveCode graphic objects
  • A 2D layer over the 3D rendering for the can of bug spray
  • Objects in the rooms made from 2D bitmaps
  • Automatic opening and closing doors
  • A captured mouse cursor for controlling the view
  • Frame rates of up to 20 fps on current hardware

Provided the processing time is under 50 ms, 20 fps is achieved. In Spider Hunt the fps is fixed to a maximum of 20 fps even if the hardware is capable of higher rates. On current hardware, achieving this is simple. In contrast, when run on my aging ThinkPad X100e Netbook from 2009 it would struggle to maintain half that.

Raycasting is a 3D technique first made popular in the 1990s in games like Ultima Underworld and Wolfenstein 3D. Then the processor of a typical home computer ran at around 66Mhz, in contrast to the 2GHz and more of today. Back then drawing an accurate 3D world like in a new game just wasn't possible.

The mathematics for drawing an accurate 3D representation of a game world was known, but the time required meant those algorithms would not result in a usuable game for the hardware of the time. When the time taken to draw a single frame is measured in seconds, or much more, a real time first person game is not possible. (Other game genres such as Adventures could have better 3D worlds, because all the image processing was done during development, for later display at runtime. (Myst is a classic game with this appoach.)

Raycasting is an algorithm that simplifies and reduces the number of calculations required to draw a 3D scene. It does this by placing restrictions on the type of world that can be represented. At the most basic, only interior rooms with walls from floor to ceiling at perpendicular angles are possible. To further simplify the processing and increase the speed, items in a room are not proper 3D models, but are instead 2D images.

Despite these limitations, and because there was nothing better, raycasting was used in many successful games. And if you have an idea that doesn't require realism, raycasting could still be used for an indie game today.

Spider Hunt is a first attempt at raycasting with LiveCode. It has problems and limitations even more restrictive than those early games. For example:

  • Sometimes the spiders pop in and out view, or flicker
  • Walls with an exposed corner do not render correctly at some viewing angles
  • The walls are not textured

The first two problems could be solved with more work, but I suspect texturing the walls is simply asking too much from the LiveCode engine that is not designed for 3D effects.

While there are many implementations of the raycasting algorithm, most are not suited to an interpreted language like LiveCode. For example, an implementation written in C++ does not need to be as carefully optimised because it runs as compiled machine code.

When designing Spider Hunt, I based it on a simple raycasting demo written in Lua. This is by Andrew Burch and can be found here. Since Lua is interpreted like LiveCode, that design is a more suitable basis for a LiveCode raycaster.

The central idea in raycasting is that the view of the world in front of the viewer, often referred to as the camera, is divided into a series of thin vertical slices going from left to right across the field of view. To make a 3D effect, the height of each slice is determined by how far away it is from the viewer.

To reduce the number of calculations, the world is divided into a grid. The grid can be thought of as tiles on the floor that are either empty, or contain a block that makes up part of a wall. This is the essence of basic raycasting, and by pre-calculating the trigonometric values needed, acceptable frame rates can be achieved.

If you are interested in the details of how raycasting works, these tutorials Ray-Casting Tutorial For Game Development And Other Purposes and Lode's Computer Graphics Tutorial Raycasting will get you started.

I am repeating myself, but LiveCode is not the best platform to use if you want to do 3D graphics without an external. What I found was that a standard implementation of the raycasting algorithm, was not going to work fast enough. This meant an alternative approach was needed.

Instead of individually rendering thin slices of wall, a LiveCode graphic object with the polygon style is used to show entire blocks of wall, as large as each tile that makes up the grid. Once this change was made, which was complex to code, achieving a frame rate of 20 fps on current hardware was possible.

As an experiment, achieving empty rooms was satisfying but boring. To add interest a simple way of including bitmaps in the room was added. The size of the bitmap varies according to the distance from the viewer to produce a 3D effect. But since the bitmap is not a 3D model, the spiders in Spider Hunt always face the viewer. Then doors were added which were surprisingly easy to code, although they are not very realistic in operation.

Lastly, a way to kill the spiders was added, which uses a simple 2D layer over the raycasting. With a spray can bitmap and an animation for the cloud of bug spray. The cloud animation was made in Anime Studio which can produce this sort of animation in minutes. Spray the spider long enough and it disappears. (If you have trouble killing it, try moving so the cross hair is over the back of the abdomen.)

That's it. A LiveCode "game" based on raycasting. Without having unrealistic expectations, things to improve in this could be:

  • Make the spiders move towards the viewer
  • A health bar that falls when a spider is too close
  • Fixing the visible glitches
  • Allowing looking up and down

When running Spider Hunt, note that the mouse cursor is "captured" and made invisible, so you cannot leave the game window with the mouse. To get the mouse back, press the Esc key.

Download the standalone LiveCode Spider Hunter executables from here:

Happy Hunting.

Tagged: 3D advanced

Monday, February 17, 2014

0 Responses

Be the first to make a comment.


COMMENTS ARE CLOSED

 

Legal Stuff

All blog posts are copyright and cannot be re-used without permission. But all the code and scripts are dedicated to the public domain. Use such code and scripts in any way you want, but I am not responsible if they don't work for you.

Contact

Further comments or feedback? You can contact me by email at: