mirror of
https://github.com/pyscript/pyscript.git
synced 2022-05-01 19:47:48 +03:00
212 lines
5.7 KiB
JavaScript
212 lines
5.7 KiB
JavaScript
(function() {
|
|
if (typeof Mario === 'undefined')
|
|
window.Mario = {};
|
|
|
|
var Koopa = Mario.Koopa = function(pos, sprite, para) {
|
|
this.dying = false;
|
|
this.shell = false;
|
|
|
|
this.para = para; //para. As in, is it a paratroopa?
|
|
|
|
//So, funny story. The actual hitboxes don't reach all the way to the ground.
|
|
//What that means is, as long as I use them to keep things on the floor
|
|
//making the hitboxes accurate will make enemies sink into the ground.
|
|
Mario.Entity.call(this, {
|
|
pos: pos,
|
|
sprite: sprite,
|
|
hitbox: [2,8,12,24]
|
|
});
|
|
this.vel[0] = -0.5;
|
|
this.idx = level.enemies.length;
|
|
};
|
|
|
|
Koopa.prototype.render = function(ctx, vX, vY) {
|
|
this.sprite.render(ctx, this.pos[0], this.pos[1], vX, vY);
|
|
};
|
|
|
|
Koopa.prototype.update = function(dt, vX) {
|
|
if (this.turn) {
|
|
this.vel[0] = -this.vel[0];
|
|
if (this.shell) sounds.bump.play();
|
|
this.turn = false;
|
|
}
|
|
if (this.vel[0] != 0) {
|
|
this.left = (this.vel[0] < 0);
|
|
}
|
|
|
|
if (this.left) {
|
|
this.sprite.img = 'sprites/enemy.png';
|
|
} else {
|
|
this.sprite.img = 'sprites/enemyr.png';
|
|
}
|
|
|
|
if (this.pos[0] - vX > 336) { //if we're too far away, do nothing.
|
|
return;
|
|
} else if (this.pos[0] - vX < -32) {
|
|
delete level.enemies[this.idx];
|
|
}
|
|
|
|
if (this.dying) {
|
|
this.dying -= 1;
|
|
if (!this.dying) {
|
|
delete level.enemies[this.idx];
|
|
}
|
|
}
|
|
|
|
if (this.shell) {
|
|
if (this.vel[0] == 0) {
|
|
this.shell -= 1;
|
|
if (this.shell < 120) {
|
|
this.sprite.speed = 5;
|
|
}
|
|
if (this.shell == 0) {
|
|
this.sprite = level.koopaSprite();
|
|
this.hitbox = [2,8,12,24]
|
|
if (this.left) {
|
|
this.sprite.img = 'sprites/enemyr.png';
|
|
this.vel[0] = 0.5;
|
|
this.left = false;
|
|
} else {
|
|
this.vel[0] = -0.5;
|
|
this.left = true;
|
|
}
|
|
this.pos[1] -= 16;
|
|
}
|
|
} else {
|
|
this.shell = 360;
|
|
this.sprite.speed = 0;
|
|
this.sprite.setFrame(0);
|
|
}
|
|
}
|
|
this.acc[1] = 0.2;
|
|
this.vel[1] += this.acc[1];
|
|
this.pos[0] += this.vel[0];
|
|
this.pos[1] += this.vel[1];
|
|
this.sprite.update(dt);
|
|
};
|
|
|
|
Koopa.prototype.collideWall = function() {
|
|
//This stops us from flipping twice on the same frame if we collide
|
|
//with multiple wall tiles simultaneously.
|
|
this.turn = true;
|
|
};
|
|
|
|
Koopa.prototype.checkCollisions = function() {
|
|
var h = this.shell ? 1 : 2;
|
|
if (this.pos[1] % 16 !== 0) {
|
|
h += 1;
|
|
}
|
|
var w = this.pos[0] % 16 === 0 ? 1 : 2;
|
|
|
|
var baseX = Math.floor(this.pos[0] / 16);
|
|
var baseY = Math.floor(this.pos[1] / 16);
|
|
|
|
if (baseY + h > 15) {
|
|
delete level.enemies[this.idx];
|
|
return;
|
|
}
|
|
|
|
if (this.flipping) {
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < h; i++) {
|
|
for (var j = 0; j < w; j++) {
|
|
if (level.statics[baseY + i][baseX + j]) {
|
|
level.statics[baseY + i][baseX + j].isCollideWith(this);
|
|
}
|
|
if (level.blocks[baseY + i][baseX + j]) {
|
|
level.blocks[baseY + i][baseX + j].isCollideWith(this);
|
|
}
|
|
}
|
|
}
|
|
var that = this;
|
|
level.enemies.forEach(function(enemy){
|
|
if (enemy === that) { //don't check collisions with ourselves.
|
|
return;
|
|
} else if (enemy.pos[0] - vX > 336){ //stop checking once we get to far away dudes.
|
|
return;
|
|
} else {
|
|
that.isCollideWith(enemy);
|
|
}
|
|
});
|
|
this.isCollideWith(player);
|
|
};
|
|
|
|
Koopa.prototype.isCollideWith = function(ent) {
|
|
if (ent instanceof Mario.Player && (this.dying || ent.invincibility)) {
|
|
return;
|
|
}
|
|
|
|
//the first two elements of the hitbox array are an offset, so let's do this now.
|
|
var hpos1 = [this.pos[0] + this.hitbox[0], this.pos[1] + this.hitbox[1]];
|
|
var hpos2 = [ent.pos[0] + ent.hitbox[0], ent.pos[1] + ent.hitbox[1]];
|
|
|
|
//if the hitboxes actually overlap
|
|
if (!(hpos1[0] > hpos2[0]+ent.hitbox[2] || (hpos1[0]+this.hitbox[2] < hpos2[0]))) {
|
|
if (!(hpos1[1] > hpos2[1]+ent.hitbox[3] || (hpos1[1]+this.hitbox[3] < hpos2[1]))) {
|
|
if (ent instanceof Mario.Player) {
|
|
if (ent.vel[1] > 0) {
|
|
player.bounce = true;
|
|
}
|
|
if (this.shell) {
|
|
sounds.kick.play();
|
|
if (this.vel[0] === 0) {
|
|
if (ent.left) { //I'm pretty sure this isn't the real logic.
|
|
this.vel[0] = -4;
|
|
} else {
|
|
this.vel[0] = 4;
|
|
}
|
|
} else {
|
|
if (ent.bounce) {
|
|
this.vel[0] = 0;
|
|
} else ent.damage();
|
|
}
|
|
} else if (ent.vel[1] > 0) { //then we get BOPPED.
|
|
this.stomp();
|
|
} else { //or the player gets hit
|
|
ent.damage();
|
|
}
|
|
} else {
|
|
if (this.shell && (ent instanceof Mario.Goomba)) {
|
|
ent.bump();
|
|
} else this.collideWall();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Koopa.prototype.stomp = function() {
|
|
//Turn this thing into a shell if it isn't already. Kick it if it is.
|
|
player.bounce = true;
|
|
if (this.para) {
|
|
this.para = false;
|
|
this.sprite.pos[0] -= 32;
|
|
} else {
|
|
sounds.stomp.play();
|
|
this.shell = 360;
|
|
this.sprite.pos[0] += 64;
|
|
this.sprite.pos[1] += 16;
|
|
this.sprite.size = [16,16];
|
|
this.hitbox = [2,0,12,16];
|
|
this.sprite.speed = 0;
|
|
this.frames = [0,1];
|
|
this.vel = [0,0];
|
|
this.pos[1] += 16;
|
|
}
|
|
|
|
};
|
|
|
|
Koopa.prototype.bump = function() {
|
|
sounds.kick.play();
|
|
if (this.flipping) return;
|
|
this.flipping = true;
|
|
this.sprite.pos = [160, 0];
|
|
this.sprite.size = [16,16];
|
|
this.hitbox = [2, 0, 12, 16];
|
|
this.sprite.speed = 0;
|
|
this.vel[0] = 0;
|
|
this.vel[1] = -2.5;
|
|
};
|
|
})();
|