The goal for this weekend: add goals.
But before I get to that, I wanted to add a simple animation to the soccer ball. I want to add animation to the frog too, but it's been a busy week. Anyway, I just wanted the ball to spin when the frog kicks it, and the speed of rotation to slow down as the forward motion of the ball slows down.
Here is an animated GIF I created of the game to illustrate what I mean.
So it behaves like a real soccer ball - it appears to roll in a more-or-less realistic manner.
Here's what I had to do in order to achieve this effect.
First, I needed to create a sprite sheet of all the frames of the ball's rotation. I used Inkscape and the GIMP to create a 45x360 pixel image of the ball at different phases of spin. A single frame of the animation is 45x45.
soccer ball spritesheet |
function preload() { game.load.image('tree2', 'images/tree2.png'); game.load.image('frog', 'images/frog.png'); game.load.spritesheet('ball', 'images/ball_animation.png', 45, 45); }
I then added another variable for the animation, and put it in the proper scope to be referenced by both the create and update functions. After creating the ball sprite like normal, I create the animation named "roll" by calling ball.animations.add("roll").
var frog; var tree; var ball; var group; var cursors; var anim; function create() { group = game.add.group(); // ... create other sprites ... ball = group.create(300, 300, 'ball'); game.physics.enable(ball, Phaser.Physics.ARCADE); ball.body.bounce.set(1); ball.body.drag.set(20); ball.body.allowGravity = false; ball.body.setSize(45, 35, 0, 8); ball.body.collideWorldBounds = true; anim = ball.animations.add("roll"); // ... other stuff ... }
The tricky part comes in the update function. I check and use the velocity of the ball to determine if the animation should be playing and how fast it should run. Look at the code below:
if (ball.body.velocity.x == 0 && ball.body.velocity.y == 0) { anim.stop(); } else { var speed = Math.min(1, Math.max(Math.abs(ball.body.velocity.x), Math.abs(ball.body.velocity.y)) / 200) * 9; if (anim.isPlaying) { anim.speed = speed; } else { anim.play(speed, true); } }
If the ball has no velocity on either the x or y axis then it is not moving at all. In that case, stop the animation. Otherwise, I calculate the animation speed. In Phaser, animation speed is specified in frames per second and has a minimum value of 1. I want the maximum frame speed to be 9, and I want to use that when the velocity of the ball is equal to or greater than 200. Velocities under 200 will calculate an animation frame rate as a ratio, but not go under 1. A velocity of 100 will result in a frame rate of 4.5, for example. If the animation is already playing, I just change the speed. If the animation is not currently playing, I start it at the calculated speed.
I am very happy with how it turned out.
I know I haven't made this code available on GitHub yet, but I will soon. Like tomorrow. For today, though, just read the comic.
Amphibian.com comic for 17 July 2015 |
No comments:
Post a Comment