R
B
code

# 2D Procedural Graphics with WebGL – Tornado Attack from My Game RoboBot

After finishing my first game Bad Blaster in 2015, I started making another one called RoboBot. I had spent a lot of time on the artwork for Bad Blaster, and so for RoboBot I wanted a simpler graphical design that was still visually impressive. I then went on a rampage and created all kinds of really cool effects using nothing but triangles, circles, and squares.

One of my favorites was a Water Spout attack.

I created it using nothing but triangles, and today I'm going to recreate it using html canvas and WebGL.

## 1. Learn WebGL

The game was written in Java and used the LibGDX framework. For this post, I wanted to embed the working code onto the page. This required me to learn the basics (very basics) of WebGL. The end code I used relies heavily on the MDN tutorial on WebGL. The parts where it differs, however, are where I make it do what I want.

## 2. Define the problem

The original problem was that I wanted to make a cool water-based attack for a game and I didn't have the resources available to animate it. The attack I settled on was a water spout, because it can attack vertically. The constraints were that I had to do the entire attack using triangles, color gradients, and color shifting. Also, performance in games is always important.

A waterspout is basically a water tornado, and I had to examine the shape and motion of a tornado. We know that tornadoes seem to be basically warped triangles, in that they have a triangle shape whose center sways at it reches the ground. For gameplay purposes, I needed the center to remain at the player's center. But I still needed the swaying motion to keep it consistent with real-world tornados. The sine and cosine functions are perfect for swaying like this. What I ended up doing was having a linear equation moving away from the center, for example f(x) = 2x. Then I modified the result by having the distance away from the center changed by a sine function. I treated x and y separately. Y was always constant; x could change. The controlling factor was the number of points, or i. I looped through an array of length 24 and used the index to process the values necessary for x and y.

I had to do this for each of the four parts of the waterspout: top left, top right, bottom left, and bottom right. Other than x, y, and the index, the other factor was the stateTime. stateTime is the only part that changes; it was run through sine function to cause the tornado to move.

```    function update(time){
// console.log(delta);
time *= 0.002;
stateTime = time;
var delta = stateTime - then;
then = stateTime;

for (var i = 0; i < count; i++) {
// top left
x = ox - width - 4*i - 24 * Math.sin(stateTime - Math.PI/6*i);
y = oy + height*i;
topLeft[i].x = x;
topLeft[i].y = y;

// top right
x = ox + width + 4*i - 24 * Math.sin(stateTime - Math.PI/6*i);
y = oy + height*i;
topRight[i].x = x;
topRight[i].y = y;

// bottom left
x = ox - width - 4*i - 24 * Math.sin(stateTime + Math.PI/6*i);
y = oy - height*i;
bottomLeft[i].x = x;
bottomLeft[i].y = y;

// bottom right
x = ox + width + 4*i - 24 * Math.sin(stateTime + Math.PI/6*i);
y = oy - height*i;
bottomRight[i].x = x;
bottomRight[i].y = y;
}
updateColors(delta);
render();
requestAnimationFrame(update);
}
```
Comments:
Leave a Comment
Submit