Advertisement

Question about 2D Animation & Programming

Started by July 19, 2021 09:21 PM
4 comments, last by Tom Sloper 2 years, 11 months ago

Hi,

I have worked on prototyping a few different 2D games in the last year, and I have started to realize how much time making animations can take. This includes traditional animation (frame-by-frame), and skeletal animation programs l like spine2D. I sometimes prefer the look of traditional animation, but I have seen some amazing animations made in spine2D.

I am wondering what is the most common method used for 2D animations, in video games? or is it, just, whatever the studio desires to use?
Is performance a concern when skeletal animations are imported into a game engine?

I have some experience with Unreal, but I have spent much more time with Unity. I know that, from my experience the skeletal animation programs also rely on plugins for whatever game engine they need to be imported into; so, I understand how some lesser known skeletal animation programs can end up losing support.

Any thoughts, opinions, or help is appreciated.

Well, the method used for 2D animations in video games is up to the studio, so go with what you prefer.

Well, I don't know if performance is a concern when skeletal animations are imported into a game engine, as I don't work with skeletal animations.

I should mention I might own a company that is focused on animations, but I don't know the first thing about the animation side of things, in fact, I don't know much about how to implement those animations into the games that we work on, also we use our own game engine that is not released to the general public, so we have never run into a problem before when we do things as our programs just minimize everything on the client-side of things, but that is with our unreleased programs, so one-day things could get easier to programmers when we release our programs, but that will be in years from now, as we run into a lot of errors when we test stuff out, like 90% of the functionality of our programs are not really working properly and we are know were done with locating the problems in the massive pile of code that make up our programs witch are all in just one app, we are having a lot of problems, after all almost all of our projects are currently on hold.

– Erik P. Kountzman - Owner - of - Airent Animation Entertainment --

Advertisement

Make template animations.

This is my simple example of sprite animation in WebGL 2.0:

Sprite sheet:

JavaScript version, GitHub: https://github.com/8Observer8/fang-idle-sprite-animation-webgl2-js
JavaScript version, Sandbox: https://plnkr.co/edit/deINAH86rUcDgry4?preview

TypeScript version, GitHub: https://github.com/8Observer8/fang-idle-sprite-animation-webgl2-ts
TypeScript version, Sandbox: https://plnkr.co/edit/lpEfcivRWP2tKUI2?preview

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Fang Idle Sprite Animation. WebGL 2.0, JavaScript</title>

    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.4.3/gl-matrix-min.js"></script>
</head>

<body>
    <canvas id="renderCanvas" width="300" height="300"></canvas>

    <script>
        const canvas = document.getElementById("renderCanvas");
        const gl = canvas.getContext("webgl2");

        const vertShaderSrc =
            `#version 300 es
            in vec2 aPosition;
            in vec2 aTexCoord;
            uniform mat4 uMvpMatrix;
            out vec2 vTexCoord;
            void main()
            {
                gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);
                vTexCoord = aTexCoord;
            }`;

        const fragShaderSrc =
            `#version 300 es
            precision mediump float;
            uniform sampler2D uSampler;
            in vec2 vTexCoord;
            out vec4 fragColor;
            void main()
            {
                fragColor = texture(uSampler, vTexCoord);
            }`;

        const vShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vShader, vertShaderSrc);
        gl.compileShader(vShader);
        let ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
        if (!ok) { console.log(gl.getShaderInfoLog(vShader));; }

        const fShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fShader, fragShaderSrc);
        gl.compileShader(fShader);
        ok = gl.getShaderParameter(fShader, gl.COMPILE_STATUS);
        if (!ok) { console.log(gl.getShaderInfoLog(fShader));; }

        const program = gl.createProgram();
        gl.attachShader(program, vShader);
        gl.attachShader(program, fShader);
        gl.linkProgram(program);
        ok = gl.getProgramParameter(program, gl.LINK_STATUS);
        if (!ok) { console.log(gl.getProgramInfoLog(program)); }
        gl.useProgram(program);

        const aPositionLocation = gl.getAttribLocation(program, "aPosition");
        const aTexCoordLocation = gl.getAttribLocation(program, "aTexCoord");

        const vertPositions = [
            -0.5, -0.5, // frame 00
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 01
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 02
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5,
            -0.5, -0.5, // frame 03
            0.5, -0.5,
            -0.5, 0.5,
            0.5, 0.5
        ];
        const vertPosVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertPosVBO);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW);
        gl.vertexAttribPointer(aPositionLocation, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aPositionLocation);

        const texCoords = [
            0, 1, // frame 00
            1 / 4, 1,
            0, 0,
            1 / 4, 0,
            1 / 4, 1, // frame 01
            2 / 4, 1,
            1 / 4, 0,
            2 / 4, 0,
            2 / 4, 1, // frame 02
            3 / 4, 1,
            2 / 4, 0,
            3 / 4, 0,
            3 / 4, 1, // frame 03
            1, 1,
            3 / 4, 0,
            1, 0
        ];
        const texCoordVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordVBO);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords), gl.STATIC_DRAW);
        gl.vertexAttribPointer(aTexCoordLocation, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(aTexCoordLocation);

        const projMatrix = glMatrix.mat4.create();
        glMatrix.mat4.ortho(projMatrix, 0, 100, 0, 100, 100, -100);

        const viewMatrix = glMatrix.mat4.create();
        glMatrix.mat4.lookAt(viewMatrix, [0, 0, 90], [0, 0, 0], [0, 1, 0]);

        const projViewMatrix = glMatrix.mat4.create();
        const mvpMatrix = glMatrix.mat4.create();
        const modelMatrix = glMatrix.mat4.create();

        glMatrix.mat4.mul(projViewMatrix, projMatrix, viewMatrix);

        const uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
        const uSamplerLocation = gl.getUniformLocation(program, "uSampler");
        gl.uniform1i(uSamplerLocation, 0);

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
        gl.clearColor(0.93, 0.95, 0.98, 1);

        let currentTime, lastTime, deltaTime;
        let animationTime = 0;
        const timePeriod = 250;
        let drawingIndex = 0;

        const image = new Image();
        image.onload =
            () =>
            {
                gl.activeTexture(gl.TEXTURE0);

                const texture = gl.createTexture();
                gl.bindTexture(gl.TEXTURE_2D, texture);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

                glMatrix.mat4.identity(modelMatrix);
                glMatrix.mat4.translate(modelMatrix, modelMatrix, [50, 50, 0]);
                // glMatrix.mat4.rotateZ(modelMatrix, modelMatrix, 30 * Math. PI / 180);
                glMatrix.mat4.scale(modelMatrix, modelMatrix, [40, 50, 1]);
                glMatrix.mat4.mul(mvpMatrix, projViewMatrix, modelMatrix);
                gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix);

                lastTime = Date.now();
                animationLoop();
            };
        image.src = "assets/fang-idle.png";

        function animationLoop()
        {
            requestAnimationFrame(() => animationLoop());

            currentTime = Date.now();
            deltaTime = currentTime - lastTime;
            lastTime = currentTime;

            animationTime += deltaTime;
            if (animationTime >= timePeriod)
            {
                animationTime = 0;

                gl.clear(gl.COLOR_BUFFER_BIT);
                gl.drawArrays(gl.TRIANGLE_STRIP, drawingIndex, 4);

                drawingIndex += 4;
                if (drawingIndex >= 16) { drawingIndex = 0; }
            }
        }
    </script>
</body>

</html>

Hey folks, the question was asked last July, and the OP has not been back to the site since. Thread locked.

-- Tom Sloper -- sloperama.com

This topic is closed to new replies.

Advertisement