Actionscript 3.0鼠标追踪蛇游戏逻辑
Actionscript 3.0 Mouse trail snake game logic
我正在用 actionscript 3.0 (adobe flash) 开发一款类似于此 https://www.tvokids.com/preschool/games/caterpillar-count 的游戏。我有将蛇头拖向鼠标方向的代码。但是,我不知道如何添加蛇的 body 并使其跟随头部的路径。以下是我在鼠标方向拖动动画片段的代码:
var _isActive = true;
var _moveSpeedMax:Number = 1000;
var _rotateSpeedMax:Number = 15;
var _decay:Number = .98;
var _destinationX:int = 150;
var _destinationY:int = 150;
var _dx:Number = 0;
var _dy:Number = 0;
var _vx:Number = 0;
var _vy:Number = 0;
var _trueRotation:Number = 0;
var _player;
var i;
createPlayer();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
function createPlayer():void{
_player = new head();
_player.x = stage.stageWidth / 2;
_player.y = stage.stageHeight / 2;
stage.addChild(_player);
}
function onDown(e:MouseEvent):void{
_isActive = true;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onMove(e:MouseEvent):void{
updatePosition(_player);
updateRotation(_player);
}
function onUp(e:MouseEvent):void{
_isActive = false;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
}
function updatePosition(mc):void
{
// check if mouse is down
if (_isActive)
{
// update destination
_destinationX = stage.mouseX;
_destinationY = stage.mouseY;
// update velocity
_vx += (_destinationX - mc.x) / _moveSpeedMax;
_vy += (_destinationY - mc.y) / _moveSpeedMax;
}
else
{
// when mouse is not down, update velocity half of normal speed
_vx += (_destinationX - mc.x) / _moveSpeedMax * .25;
_vy += (_destinationY - mc.y) / _moveSpeedMax * .25;
}
// apply decay (drag)
_vx *= _decay;
_vy *= _decay;
// if close to target, slow down turn speed
if (getDistance(_dx, _dy) < 50)
{
_trueRotation *= .5;
}
// update position
mc.x += _vx;
mc.y += _vy;
}
function updateRotation(mc):void
{
// calculate rotation
_dx = mc.x - _destinationX;
_dy = mc.y - _destinationY;
// which way to rotate
var rotateTo:Number = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > mc.rotation + 180) rotateTo -= 360;
if (rotateTo < mc.rotation - 180) rotateTo += 360;
// ease rotation
_trueRotation = (rotateTo - mc.rotation) / _rotateSpeedMax;
// update rotation
mc.rotation += _trueRotation;
}
function getDistance(delta_x:Number, delta_y:Number):Number
{
return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y));
}
function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
r += (2 * Math.PI);
}
return r;
}
function getDegrees(radians:Number):Number
{
return Math.floor(radians/(Math.PI/180));
}
下面的脚本不会奇迹般地单独运行,但它具有您需要的所有逻辑,并得到了很好的解释。它使任何长度的链条都按照一定的规则跟随其头部。很多年前我在这里使用了相同的原则:http://delimiter.ru/games/25-lines/alone.html
// This one will represent the Mouse position.
var Rat:Sprite = new Sprite;
// The ordered list of chain elements.
// It all starts with the Mouse.
var Snake:Array = [Rat];
// Call this one each time you want to
// extend the snake with the piece of tail.
function addTail(aPiece:DisplayObject):void
{
// Get the last snake element.
var lastPiece:DisplayObject = Snake[Snake.length - 1];
// Sync the tail coordinates.
aPiece.x = lastPiece.x;
aPiece.y = lastPiece.y;
// Add the new piece to the snake.
Snake.push(aPiece);
}
// Add the pre-defined head as the first element.
addTail(SnakeHead);
// Now start following the Mouse.
addEventListener(Event.ENTER_FRAME, onFrame);
// Fires every frame and adjusts the whole snake, if needed.
function onFrame(e:Event):void
{
// Sync the attractor point with the Mouse.
Rat.x = mouseX;
Rat.y = mouseY;
// Now lets make each piece follow the previous piece,
// one by one, starting from the head, down to the tail.
for (var i:int = 1; i < Snake.length; i++)
{
followOne(Snake[i - 1], Snake[i]);
}
}
function followOne(A:DisplayObject, B:DisplayObject):void
{
// Think of these values as of vector
// pointing from B position to A position.
var dx:Number = A.x - B.x;
var dy:Number = A.y - B.y;
// Figure out the distance between the given pieces.
var aDist:Number = Math.sqrt(dx * dx + dy * dy);
// Do nothing if pieces are closer than 20 px apart.
// You can change this value to make snake shorter or longer.
if (aDist < 20)
{
return;
}
// This literally means "eat one tenth of the distance
// between me and the previous piece". If you want pieces
// to follow each other with more vigor, reduce this value,
// if you want the whole snake to slither smoothly, increase it.
B.x += dx / 10;
B.y += dy / 10;
// Rotate the B piece so it would look right into A's direction.
// Well, unless your pieces are round and look all the same.
B.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
}
我正在用 actionscript 3.0 (adobe flash) 开发一款类似于此 https://www.tvokids.com/preschool/games/caterpillar-count 的游戏。我有将蛇头拖向鼠标方向的代码。但是,我不知道如何添加蛇的 body 并使其跟随头部的路径。以下是我在鼠标方向拖动动画片段的代码:
var _isActive = true;
var _moveSpeedMax:Number = 1000;
var _rotateSpeedMax:Number = 15;
var _decay:Number = .98;
var _destinationX:int = 150;
var _destinationY:int = 150;
var _dx:Number = 0;
var _dy:Number = 0;
var _vx:Number = 0;
var _vy:Number = 0;
var _trueRotation:Number = 0;
var _player;
var i;
createPlayer();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
function createPlayer():void{
_player = new head();
_player.x = stage.stageWidth / 2;
_player.y = stage.stageHeight / 2;
stage.addChild(_player);
}
function onDown(e:MouseEvent):void{
_isActive = true;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onMove(e:MouseEvent):void{
updatePosition(_player);
updateRotation(_player);
}
function onUp(e:MouseEvent):void{
_isActive = false;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
}
function updatePosition(mc):void
{
// check if mouse is down
if (_isActive)
{
// update destination
_destinationX = stage.mouseX;
_destinationY = stage.mouseY;
// update velocity
_vx += (_destinationX - mc.x) / _moveSpeedMax;
_vy += (_destinationY - mc.y) / _moveSpeedMax;
}
else
{
// when mouse is not down, update velocity half of normal speed
_vx += (_destinationX - mc.x) / _moveSpeedMax * .25;
_vy += (_destinationY - mc.y) / _moveSpeedMax * .25;
}
// apply decay (drag)
_vx *= _decay;
_vy *= _decay;
// if close to target, slow down turn speed
if (getDistance(_dx, _dy) < 50)
{
_trueRotation *= .5;
}
// update position
mc.x += _vx;
mc.y += _vy;
}
function updateRotation(mc):void
{
// calculate rotation
_dx = mc.x - _destinationX;
_dy = mc.y - _destinationY;
// which way to rotate
var rotateTo:Number = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > mc.rotation + 180) rotateTo -= 360;
if (rotateTo < mc.rotation - 180) rotateTo += 360;
// ease rotation
_trueRotation = (rotateTo - mc.rotation) / _rotateSpeedMax;
// update rotation
mc.rotation += _trueRotation;
}
function getDistance(delta_x:Number, delta_y:Number):Number
{
return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y));
}
function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
r += (2 * Math.PI);
}
return r;
}
function getDegrees(radians:Number):Number
{
return Math.floor(radians/(Math.PI/180));
}
下面的脚本不会奇迹般地单独运行,但它具有您需要的所有逻辑,并得到了很好的解释。它使任何长度的链条都按照一定的规则跟随其头部。很多年前我在这里使用了相同的原则:http://delimiter.ru/games/25-lines/alone.html
// This one will represent the Mouse position.
var Rat:Sprite = new Sprite;
// The ordered list of chain elements.
// It all starts with the Mouse.
var Snake:Array = [Rat];
// Call this one each time you want to
// extend the snake with the piece of tail.
function addTail(aPiece:DisplayObject):void
{
// Get the last snake element.
var lastPiece:DisplayObject = Snake[Snake.length - 1];
// Sync the tail coordinates.
aPiece.x = lastPiece.x;
aPiece.y = lastPiece.y;
// Add the new piece to the snake.
Snake.push(aPiece);
}
// Add the pre-defined head as the first element.
addTail(SnakeHead);
// Now start following the Mouse.
addEventListener(Event.ENTER_FRAME, onFrame);
// Fires every frame and adjusts the whole snake, if needed.
function onFrame(e:Event):void
{
// Sync the attractor point with the Mouse.
Rat.x = mouseX;
Rat.y = mouseY;
// Now lets make each piece follow the previous piece,
// one by one, starting from the head, down to the tail.
for (var i:int = 1; i < Snake.length; i++)
{
followOne(Snake[i - 1], Snake[i]);
}
}
function followOne(A:DisplayObject, B:DisplayObject):void
{
// Think of these values as of vector
// pointing from B position to A position.
var dx:Number = A.x - B.x;
var dy:Number = A.y - B.y;
// Figure out the distance between the given pieces.
var aDist:Number = Math.sqrt(dx * dx + dy * dy);
// Do nothing if pieces are closer than 20 px apart.
// You can change this value to make snake shorter or longer.
if (aDist < 20)
{
return;
}
// This literally means "eat one tenth of the distance
// between me and the previous piece". If you want pieces
// to follow each other with more vigor, reduce this value,
// if you want the whole snake to slither smoothly, increase it.
B.x += dx / 10;
B.y += dy / 10;
// Rotate the B piece so it would look right into A's direction.
// Well, unless your pieces are round and look all the same.
B.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
}