Select the types of activity you want to include in your feed.
[READ-ONLY] Mirror of https://github.com/flo-bit/shadow-shmup. Fun and casual top-down, roguelike shoot 'em up browsergame with shadow elements and colorful neon effects
flo-bit.dev/shadow-shmup/
···11-import Game from './app';
22-import { Projectile } from './projectile';
11+import Game from '../app';
22+import { Projectile } from '../projectile';
3344import { sound } from '@pixi/sound';
55···2020 piercing?: number;
2121};
22222323-export class Weapon {
2323+export class GunWeapon {
2424 game: Game;
25252626 cooldown: number = 0;
+76
src/weapons/ball.ts
···11+import Game from '../app';
22+import { Light } from '../light';
33+import * as PIXI from 'pixi.js';
44+import { RAPIER } from '../rapier';
55+import { Collider, RigidBody } from '@dimforge/rapier2d';
66+import { Weapon } from './weapon';
77+88+/**
99+ * ball that flies in a circle around player
1010+ */
1111+export class BallWeapon extends Weapon {
1212+ distance: number = 200;
1313+ speed: number = 0.002;
1414+ angle: number = 0;
1515+1616+ constructor(game: Game, color: number) {
1717+ super(game, color);
1818+1919+ this.shape = new PIXI.Graphics().circle(0, 0, this.size).fill(this.color);
2020+ for (let i = 0; i < 10; i++) {
2121+ let angle1 = (Math.PI * 2 * i) / 10;
2222+ let angle2 = (Math.PI * 2 * (i + 1)) / 10;
2323+ let angleBetween = (Math.PI * 2 * (i + 0.5)) / 10;
2424+2525+ let x1 = Math.cos(angle1) * this.size;
2626+ let y1 = Math.sin(angle1) * this.size;
2727+ let x2 = Math.cos(angle2) * this.size;
2828+ let y2 = Math.sin(angle2) * this.size;
2929+ let x3 = Math.cos(angleBetween) * this.size * 1.5;
3030+ let y3 = Math.sin(angleBetween) * this.size * 1.5;
3131+ this.shape.poly([x1, y1, x2, y2, x3, y3]).fill(this.color);
3232+ }
3333+ this.game.container.addChild(this.shape);
3434+3535+ const rigidBodyDesc = RAPIER()
3636+ .RigidBodyDesc.kinematicPositionBased()
3737+ .setTranslation(this.shape.x, this.shape.y);
3838+ this.rigidBody = game.world.createRigidBody(rigidBodyDesc);
3939+4040+ const colliderDesc = RAPIER()
4141+ .ColliderDesc.ball(this.size * 1.5)
4242+ .setCollisionGroups(0x00040002)
4343+ .setSensor(true)
4444+ .setActiveEvents(RAPIER().ActiveEvents.COLLISION_EVENTS);
4545+4646+ this.collider = game.world.createCollider(colliderDesc, this.rigidBody);
4747+4848+ this.rigidBody.userData = this;
4949+ }
5050+5151+ set x(value: number) {
5252+ if (this.shape) this.shape.x = value;
5353+ this.rigidBody?.setTranslation({ x: value, y: -(this.shape?.y ?? 0) }, true);
5454+ }
5555+5656+ set y(value: number) {
5757+ if (this.shape) this.shape.y = value;
5858+ this.rigidBody?.setTranslation({ x: this.shape?.x ?? 0, y: -value }, true);
5959+ }
6060+6161+ update(deltaTime: number, x: number, y: number) {
6262+ this.angle += deltaTime * this.speed;
6363+6464+ this.x = x + Math.cos(this.angle) * this.distance;
6565+ this.y = y + Math.sin(this.angle) * this.distance;
6666+6767+ if (this.shape) {
6868+ this.shape.rotation = this.angle * 2;
6969+ }
7070+ }
7171+7272+ destroy() {
7373+ if (this.shape) this.shape.destroy();
7474+ if (this.rigidBody) this.game.world.removeRigidBody(this.rigidBody);
7575+ }
7676+}
+45
src/weapons/burst.ts
···11+import Game from '../app';
22+import { Light } from '../light';
33+import * as PIXI from 'pixi.js';
44+import { RAPIER } from '../rapier';
55+import { Collider, RigidBody } from '@dimforge/rapier2d';
66+import { Weapon } from './weapon';
77+import { GunWeapon } from './gun';
88+99+/**
1010+ * ball that flies in a circle around player
1111+ */
1212+export class BurstWeapon extends Weapon {
1313+ cooldown: number = 0;
1414+ fireRate: number = 1000;
1515+1616+ gun: GunWeapon;
1717+1818+ constructor(game: Game, color: number) {
1919+ super(game, color);
2020+2121+ this.gun = new GunWeapon(game, {
2222+ color: this.color,
2323+ lifetime: 200,
2424+ fireRate: 300,
2525+ projectileSpeed: 1,
2626+ projectileSize: 10,
2727+ sound: false
2828+ });
2929+ }
3030+3131+ update(deltaTime: number, x: number, y: number) {
3232+ this.gun.update(deltaTime);
3333+3434+ if (this.gun.cooldown <= 0) {
3535+ for (let i = 0; i < 20; i++) {
3636+ this.gun.cooldown = -1;
3737+ // get angle
3838+ let angle = (Math.PI / 10) * i;
3939+ let dx = Math.cos(angle) + x;
4040+ let dy = Math.sin(angle) + y;
4141+ this.gun.fire({ x, y }, { x: dx, y: dy });
4242+ }
4343+ }
4444+ }
4545+}
+83
src/weapons/knife.ts
···11+import Game from '../app';
22+import { Light } from '../light';
33+import * as PIXI from 'pixi.js';
44+import { RAPIER } from '../rapier';
55+import { Collider, RigidBody, Vector2 } from '@dimforge/rapier2d';
66+import { Weapon } from './weapon';
77+88+/**
99+ * triangle that spins and goes to left and right of player
1010+ */
1111+export class Knife extends Weapon {
1212+ speed: number = 0.006;
1313+ distance: number = 300;
1414+ current: number = 0;
1515+1616+ angle: number = 0;
1717+1818+ direction: 'left' | 'right' | 'both' = 'both';
1919+2020+ constructor(game: Game, color: number) {
2121+ super(game, color);
2222+2323+ this.shape = new PIXI.Graphics()
2424+ .poly([-this.size, -this.size / 2, this.size, -this.size / 2, 0, this.size])
2525+ .fill(this.color);
2626+2727+ this.game.container.addChild(this.shape);
2828+2929+ this.createRidigBody();
3030+ }
3131+3232+ createRidigBody(): void {
3333+ if (!this.shape) return;
3434+3535+ const rigidBodyDesc = RAPIER()
3636+ .RigidBodyDesc.kinematicPositionBased()
3737+ .setTranslation(this.shape.x, this.shape.y);
3838+ this.rigidBody = this.game.world.createRigidBody(rigidBodyDesc);
3939+4040+ const colliderDesc = RAPIER()
4141+ .ColliderDesc.ball(this.size)
4242+ .setCollisionGroups(0x00040002)
4343+ .setSensor(true)
4444+ .setActiveEvents(RAPIER().ActiveEvents.COLLISION_EVENTS);
4545+4646+ this.game.world.createCollider(colliderDesc, this.rigidBody);
4747+4848+ this.rigidBody.userData = this;
4949+ }
5050+5151+ set x(value: number) {
5252+ if (this.shape) this.shape.x = value;
5353+ this.rigidBody?.setTranslation({ x: value, y: -(this.shape?.y ?? 0) }, true);
5454+ }
5555+5656+ set y(value: number) {
5757+ if (this.shape) this.shape.y = value;
5858+ this.rigidBody?.setTranslation({ x: this.shape?.x ?? 0, y: -value }, true);
5959+ }
6060+6161+ update(deltaTime: number, x: number, y: number) {
6262+ this.current += deltaTime * this.speed;
6363+6464+ let dx = Math.cos(this.current) * this.distance;
6565+ if (this.direction === 'left') dx = -Math.abs(dx);
6666+ else if (this.direction === 'right') dx = Math.abs(dx);
6767+6868+ this.x = x + Math.cos(this.angle) * dx;
6969+ this.y = y + Math.sin(this.angle) * dx;
7070+7171+ // this.x = x + dx;
7272+ // this.y = y + Math.cos(this.current * 0.25) * this.distance * 0.05;
7373+7474+ if (this.shape) {
7575+ this.shape.rotation = this.current * 4;
7676+ }
7777+ }
7878+7979+ destroy() {
8080+ if (this.shape) this.shape.destroy();
8181+ if (this.rigidBody) this.game.world.removeRigidBody(this.rigidBody);
8282+ }
8383+}
+51
src/weapons/weapon.ts
···11+import { Collider, RigidBody } from '@dimforge/rapier2d';
22+import Game from '../app';
33+import * as PIXI from 'pixi.js';
44+55+/**
66+ * ball that flies in a circle around player
77+ */
88+export class Weapon {
99+ game: Game;
1010+1111+ size: number = 10;
1212+1313+ damage: number = 20;
1414+1515+ color: number;
1616+1717+ shape?: PIXI.Graphics;
1818+1919+ rigidBody?: RigidBody;
2020+ collider?: Collider;
2121+2222+ constructor(game: Game, color: number) {
2323+ this.game = game;
2424+2525+ this.color = color;
2626+ }
2727+2828+ get x() {
2929+ if (this.shape) this.shape?.x ?? 0;
3030+3131+ return this.rigidBody?.translation().x ?? 0;
3232+ }
3333+ set x(value) {
3434+ if (this.shape) this.shape.x = value;
3535+ this.rigidBody?.setTranslation({ x: value, y: -this.y }, true);
3636+ }
3737+3838+ get y() {
3939+ if (this.shape) return this.shape.y;
4040+4141+ return -(this.rigidBody?.translation().y ?? 0);
4242+ }
4343+ set y(value) {
4444+ if (this.shape) this.shape.y = value;
4545+ this.rigidBody?.setTranslation({ x: this.x, y: -value }, true);
4646+ }
4747+4848+ update(deltaTime: number, x: number, y: number) {}
4949+5050+ destroy() {}
5151+}