<commit_before>import * as _ from 'lodash';
import * as pag from 'pag';
import * as ppe from 'ppe';
import * as g from './index';

export const rotationNum = 16;

export interface ActorOptions {
  hasMuzzleEffect?: boolean;
  hasTrail?: boolean;
  destroyedEffect?: string;
}

export class Actor {
  pos = g.p.createVector();
  vel = g.p.createVector();
  prevPos = g.p.createVector();
  angle = 0;
  speed = 0;
  isAlive = true;
  priority = 1;
  ticks = 0;
  sprite: { pixels: pag.Pixel[][][], offset: p5.Vector }[] = [];
  type: string;
  collisionType: string;
  collision = g.p.createVector(8, 8);
  context: CanvasRenderingContext2D;
  modules: any[] = [];
  moduleNames: string[] = [];

  constructor(public options: ActorOptions = {}, public game: g.Game = g.game) {
    game.actorPool.add(this);
    this.context = game.screen.context;
    this.type = g.getClassName(this);
    new g.RemoveWhenInAndOut(this);
    this.init();
  }

  init() { }

  update() {
    if (this.options.hasMuzzleEffect && this.ticks === 0) {
      this.emitParticles(`m_${this.type}`, {}, this.game.particlePool);
    }
    if (this.options.hasTrail) {
      this.emitParticles(`t_${this.type}`, {}, this.game.particlePool);
    }
    this.prevPos.set(this.pos);
    this.pos.add(this.vel);
    this.pos.x += Math.cos(this.angle) * this.speed;
    this.pos.y += Math.sin(this.angle) * this.speed;
    if (this.sprite != null) {
      this.drawSprite();
    }
    _.forEach(this.modules, m => {
      if (m.isEnabled) {
        m.update();
      }
    });
    this.ticks++;
  }

  remove() {
    this.isAlive = false;
  }

  destroy() {
    if (this.options.destroyedEffect != null) {
      this.emitParticles(`${this.options.destroyedEffect}_${this.type}_d`,
        {},
        this.game.particlePool);
    }
    this.remove();
  }

  clearModules() {
    this.modules = [];
    this.moduleNames = [];
  }

  testCollision(type: string) {
    return _.filter<Actor>(this.game.actorPool.getByCollisionType(type), a =>
      a !== this &&
      Math.abs(this.pos.x - a.pos.x) < (this.collision.x + a.collision.x) / 2 &&
      Math.abs(this.pos.y - a.pos.y) < (this.collision.y + a.collision.y) / 2
    );
  }

  emitParticles(patternName: string, options: ppe.EmitOptions = {},
    pool: ppe.ParticlePool = null) {
    ppe.emit(patternName, this.pos.x, this.pos.y, this.angle, options, pool);
  }

  addSpritePixels(pixels: pag.Pixel[][][], offsetX = 0, offsetY = 0) {
    this.sprite.push({ pixels, offset: g.p.createVector(offsetX, offsetY) });
  }

  drawSprite(x: number = this.pos.x, y: number = this.pos.y) {
    _.forEach(this.sprite, s => {
      this.drawSpritePixels(s.pixels, x + s.offset.x, y + s.offset.y);
    });
  }

  drawSpritePixels(pixels: pag.Pixel[][][], x: number, y: number) {
    if (this.sprite.length <= 1) {
      pag.draw(this.context, pixels, x, y);
    } else {
      let a = this.angle;
      if (a < 0) {
        a = Math.PI * 2 + a % (Math.PI * 2);
      }
      const ri = Math.round(a / (Math.PI * 2 / rotationNum)) % rotationNum;
      pag.draw(this.context, pixels, x, y, ri);
    }
  }

  getModule(moduleName: string) {
    return this.modules[_.indexOf(this.moduleNames, moduleName)];<commit_msg>Fix drawing the rotating sprite bug<commit_after>import * as _ from 'lodash';
import * as pag from 'pag';
import * as ppe from 'ppe';
import * as g from './index';

export const rotationNum = 16;

export interface ActorOptions {
  hasMuzzleEffect?: boolean;
  hasTrail?: boolean;
  destroyedEffect?: string;
}

export class Actor {
  pos = g.p.createVector();
  vel = g.p.createVector();
  prevPos = g.p.createVector();
  angle = 0;
  speed = 0;
  isAlive = true;
  priority = 1;
  ticks = 0;
  sprite: { pixels: pag.Pixel[][][], offset: p5.Vector }[] = [];
  type: string;
  collisionType: string;
  collision = g.p.createVector(8, 8);
  context: CanvasRenderingContext2D;
  modules: any[] = [];
  moduleNames: string[] = [];

  constructor(public options: ActorOptions = {}, public game: g.Game = g.game) {
    game.actorPool.add(this);
    this.context = game.screen.context;
    this.type = g.getClassName(this);
    new g.RemoveWhenInAndOut(this);
    this.init();
  }

  init() { }

  update() {
    if (this.options.hasMuzzleEffect && this.ticks === 0) {
      this.emitParticles(`m_${this.type}`, {}, this.game.particlePool);
    }
    if (this.options.hasTrail) {
      this.emitParticles(`t_${this.type}`, {}, this.game.particlePool);
    }
    this.prevPos.set(this.pos);
    this.pos.add(this.vel);
    this.pos.x += Math.cos(this.angle) * this.speed;
    this.pos.y += Math.sin(this.angle) * this.speed;
    if (this.sprite != null) {
      this.drawSprite();
    }
    _.forEach(this.modules, m => {
      if (m.isEnabled) {
        m.update();
      }
    });
    this.ticks++;
  }

  remove() {
    this.isAlive = false;
  }

  destroy() {
    if (this.options.destroyedEffect != null) {
      this.emitParticles(`${this.options.destroyedEffect}_${this.type}_d`,
        {},
        this.game.particlePool);
    }
    this.remove();
  }

  clearModules() {
    this.modules = [];
    this.moduleNames = [];
  }

  testCollision(type: string) {
    return _.filter<Actor>(this.game.actorPool.getByCollisionType(type), a =>
      a !== this &&
      Math.abs(this.pos.x - a.pos.x) < (this.collision.x + a.collision.x) / 2 &&
      Math.abs(this.pos.y - a.pos.y) < (this.collision.y + a.collision.y) / 2
    );
  }

  emitParticles(patternName: string, options: ppe.EmitOptions = {},
    pool: ppe.ParticlePool = null) {
    ppe.emit(patternName, this.pos.x, this.pos.y, this.angle, options, pool);
  }

  addSpritePixels(pixels: pag.Pixel[][][], offsetX = 0, offsetY = 0) {
    this.sprite.push({ pixels, offset: g.p.createVector(offsetX, offsetY) });
  }

  drawSprite(x: number = this.pos.x, y: number = this.pos.y) {
    _.forEach(this.sprite, s => {
      this.drawSpritePixels(s.pixels, x + s.offset.x, y + s.offset.y);
    });
  }

  drawSpritePixels(pixels: pag.Pixel[][][], x: number, y: number) {
    if (pixels.length <= 1) {
      pag.draw(this.context, pixels, x, y);
    } else {
      let a = this.angle;
      if (a < 0) {
        a = Math.PI * 2 + a % (Math.PI * 2);
      }
      const ri = Math.round(a / (Math.PI * 2 / rotationNum)) % rotationNum;
      pag.draw(this.context, pixels, x, y, ri);
    }
  }

  getModule(moduleName: string) {
    return this.modules[_.indexOf(this.moduleNames, moduleName)];
{'fraction_non_alphanumeric': 0.1769075994428107, 'fraction_numerical': 0.006190992106485064, 'mean_word_length': 2.776738749269433, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5345606', 'n_tokens_mistral': 2406, 'n_tokens_neox': 2355, 'n_words': 452}