Forked from
fsini-informatik / fsfahrttool
404 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
character.js 4.19 KiB
function Char(svg, options) {
if (!options) options = {};
this.svg = svg;
this.pathFinder = new PathFinder(svg);
this.translation = options.spawn ? options.spawn : this.findSpawn();
this.moveTarget = [];
this.maxSpeed = 2;
this.loaded = false;
var self = this;
d3.xml(FAPI.resolvePath('chars/bernd.svg'), 'image/svg+xml', function(xml) {
self.image = self.svg.append('g').attr('id', 'player');
var layers = d3.select(xml.documentElement).selectAll('g').filter(function() {
return this.getAttribute('inkscape:groupmode') == 'layer';
}).each(function() {
self.image[0][0].appendChild(this);
});
self.initializeAnimations();
self.updatePosition();
self.loaded = true;
});
}
Char.prototype.findSpawn = function() {
// [1320, svgFlipY(svg[0][0], 500)]
var spawn = this.svg.select("#player_spawn");
var bbox = spawn[0][0].getBBox();
return Vec.add(getTranslation(this.svg[0][0], spawn[0][0]), [bbox.x, bbox.y]);
}
Char.prototype.initializeAnimations = function() {
var self = this;
this.animateStep = 0;
this.lastPosition = this.translation.slice();
this.lastDirection = 2;
this.currentFrame = 0;
this.frames = null;
this.animations = {};
this.image.selectAll('g').filter(function() {
return this.getAttribute('inkscape:groupmode') == 'layer';
}).each(function() {
var label = this.getAttribute('inkscape:label');
var element = d3.select(this)
.style('display', 'block');
var frames = [];
element.selectAll('image')
.style('display', 'none')
.each(function() {
frames.push(this);
});
self.animations[label] = frames;
});
}
Char.directionToName = ["UP", "RIGHT", "DOWN", "LEFT"];
Char.prototype.animate = function() {
this.animateStep += 1;
if (this.animateStep <= 8) return;
while (this.animateStep > 8)
this.animateStep -= 8;
var xSpeed = this.translation[0] - this.lastPosition[0];
var ySpeed = - this.translation[1] + this.lastPosition[1];
this.lastPosition = this.translation.slice();
var speed = Math.max(Math.abs(xSpeed), Math.abs(ySpeed)); // estimate
var direction = this.lastDirection;
if (speed > g_smallValue) {
if (Math.abs(xSpeed) >= Math.abs(ySpeed))
direction = (xSpeed >= 0) ? 1 : 3;
else
direction = (ySpeed >= 0) ? 0 : 2;
}
// hide last visible frame
if (this.frames && this.frames[this.currentFrame]) {
var lastFrame = this.frames[this.currentFrame];
lastFrame.style.display = 'none';
}
// change animation
if (direction != this.lastDirection) {
this.lastDirection = direction;
this.currentFrame = 0;
this.frames = this.animations[Char.directionToName[direction]];
}
// if no current frames available show fallback downwards frame
if (!this.frames || this.frames.length == 0)
this.frames = this.animations['DOWN'];
// if everything fails..
if (!this.frames || this.frames.length == 0)
return;
// frames depending on speed
if (speed < g_smallValue)
this.currentFrame = 0; // stand still
else
this.currentFrame += 1; // walk
this.currentFrame %= this.frames.length;
// show current frame
this.frames[this.currentFrame].style.display = 'block';
}
Char.prototype.physics = function() {
if (this.moveTarget && this.moveTarget.length == 0) return;
if (Vec.equals(this.translation, this.moveTarget[0])) {
this.moveTarget.shift();
return;
}
var v = Vec.add(Vec.flipSign(this.translation), this.moveTarget[0]);
var d = Vec.length(v);
if (d > this.maxSpeed) {
var n = Vec.mul(v, 1/d); // normalized
v = Vec.mul(n, this.maxSpeed);
}
var nextPosition = (d < g_smallValue) ? this.moveTarget[0] : Vec.add(this.translation, v);
if (this.pathFinder.canWalkOn(nextPosition[0], nextPosition[1]))
Vec.assign(this.translation, nextPosition);
else
this.moveTarget.shift();
this.updatePosition();
}
Char.prototype.updatePosition = function() {
if (!this.image) return;
var self = this;
this.image.attr("transform", function() {
return translate.apply(null, self.translation);
});
}
Char.prototype.setMoveTarget = function(newX, newY) {
var matrix = this.svg[0][0].getScreenCTM();
var x = newX-matrix.e;
var y = newY-matrix.f;
if (Game.config.usePathFinding)
this.moveTarget = this.pathFinder.smoothPath(this.pathFinder.findPath(this.translation[0], this.translation[1], x, y));
else
this.moveTarget = [[x, y]];
}