diff --git a/assets/ships/orange_attack_ship.png b/assets/ships/orange_attack_ship.png deleted file mode 100644 index 1c9f63a..0000000 Binary files a/assets/ships/orange_attack_ship.png and /dev/null differ diff --git a/assets/shots/orange_shot.png b/assets/shots/orange_shot.png deleted file mode 100644 index ed01e02..0000000 Binary files a/assets/shots/orange_shot.png and /dev/null differ diff --git a/assets/spritesheet.json b/assets/spritesheet.json new file mode 100644 index 0000000..f71d0ab --- /dev/null +++ b/assets/spritesheet.json @@ -0,0 +1,111 @@ +{ + "frames": { + "background.png": { + "frame": { "x": 1, "y": 90, "w": 800, "h": 600 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 800, "h": 600 }, + "sourceSize": { "w": 800, "h": 600 } + }, + "blue_ship.png": { + "frame": { "x": 406, "y": 1, "w": 63, "h": 51 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 63, "h": 51 }, + "sourceSize": { "w": 63, "h": 51 } + }, + "blue_shot.png": { + "frame": { "x": 25, "y": 1, "w": 16, "h": 18 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 16, "h": 18 }, + "sourceSize": { "w": 16, "h": 18 } + }, + "blue_strong_shot.png": { + "frame": { "x": 153, "y": 1, "w": 36, "h": 44 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 36, "h": 44 }, + "sourceSize": { "w": 36, "h": 44 } + }, + "enemy_ship_strong.png": { + "frame": { "x": 471, "y": 1, "w": 90, "h": 74 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 90, "h": 74 }, + "sourceSize": { "w": 90, "h": 74 } + }, + "enemy_ship_weak.png": { + "frame": { "x": 563, "y": 1, "w": 98, "h": 87 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 98, "h": 87 }, + "sourceSize": { "w": 98, "h": 87 } + }, + "green_ship.png": { + "frame": { "x": 340, "y": 1, "w": 64, "h": 47 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 47 }, + "sourceSize": { "w": 64, "h": 47 } + }, + "green_shot.png": { + "frame": { "x": 45, "y": 1, "w": 19, "h": 17 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 19, "h": 17 }, + "sourceSize": { "w": 19, "h": 17 } + }, + "meteor_gray.png": { + "frame": { "x": 115, "y": 1, "w": 31, "h": 36 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 31, "h": 36 }, + "sourceSize": { "w": 31, "h": 36 } + }, + "meteor_orange.png": { + "frame": { "x": 248, "y": 1, "w": 42, "h": 39 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 42, "h": 39 }, + "sourceSize": { "w": 42, "h": 39 } + }, + "orange_ship.png": { + "frame": { "x": 292, "y": 1, "w": 46, "h": 45 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 46, "h": 45 }, + "sourceSize": { "w": 46, "h": 45 } + }, + "orange_shot.png": { + "frame": { "x": 1, "y": 1, "w": 14, "h": 22 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 14, "h": 22 }, + "sourceSize": { "w": 14, "h": 22 } + }, + "yellow_strong_thick_shot.png": { + "frame": { "x": 199, "y": 1, "w": 36, "h": 47 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 36, "h": 47 }, + "sourceSize": { "w": 36, "h": 47 } + }, + "yellow_strong_thin_shot.png": { + "frame": { "x": 66, "y": 1, "w": 19, "h": 47 }, + "rotated": true, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 19, "h": 47 }, + "sourceSize": { "w": 19, "h": 47 } + } + }, + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.1", + "image": "spritesheet.png", + "format": "RGBA8888", + "size": { "w": 802, "h": 691 }, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:e0436f51fea5c86c85c28c892eb7f5c5:b102884fa100e0f016a1e033d5c5e2b1:729adc6043343cfda41c447ce8f464d6$" + } +} diff --git a/assets/spritesheet.png b/assets/spritesheet.png new file mode 100644 index 0000000..fb0c377 Binary files /dev/null and b/assets/spritesheet.png differ diff --git a/assets/worlds/pink_galaxy.png b/assets/worlds/pink_galaxy.png deleted file mode 100644 index 033e30e..0000000 Binary files a/assets/worlds/pink_galaxy.png and /dev/null differ diff --git a/src/Game.ts b/src/Game.ts index ca9c28a..4b6ed00 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -3,6 +3,8 @@ import World from "./core/World"; import BulletControl from "./core/BulletControl"; import BulletPool from "./Helpers/BulletPool"; import { Player } from "./core/Player"; +import InputHandler from "./core/InputHandler"; +import { EnemySpawner } from "./core/EnemySpawner"; export default class Game { static Instance: Game; @@ -11,6 +13,8 @@ export default class Game { bulletPool: BulletPool; bulletControl: BulletControl; player: Player; + inputHandler: InputHandler; + enemySpawner: EnemySpawner; constructor(app: Application) { Game.Instance = this; @@ -19,5 +23,7 @@ export default class Game { this.bulletPool = new BulletPool(); this.bulletControl = new BulletControl(); this.player = new Player(); + this.inputHandler = new InputHandler(); + this.enemySpawner = new EnemySpawner(); } } diff --git a/src/Interfaces/IAttack.ts b/src/Interfaces/IAttack.ts index 33dd63b..f4dce01 100644 --- a/src/Interfaces/IAttack.ts +++ b/src/Interfaces/IAttack.ts @@ -3,5 +3,4 @@ import IAttackStrategy from "./IAttackStrategy"; export default interface IAttack { attackStrategy: IAttackStrategy; attack(): void; - getFireInterval(): number; } diff --git a/src/Interfaces/IAttackStrategy.ts b/src/Interfaces/IAttackStrategy.ts index 9914fcf..30478f9 100644 --- a/src/Interfaces/IAttackStrategy.ts +++ b/src/Interfaces/IAttackStrategy.ts @@ -2,7 +2,7 @@ import { Point } from "pixi.js"; import Bullet from "../objects/Bullet"; export default interface IAttackStrategy { - bulletSpritePath: string; + bulletSpriteName: string; bulletPoint: Point; bulletSpeed: number; bulletDamage: number; diff --git a/src/Interfaces/IMove.ts b/src/Interfaces/IMove.ts index 9410045..3907bcd 100644 --- a/src/Interfaces/IMove.ts +++ b/src/Interfaces/IMove.ts @@ -2,5 +2,5 @@ import IMoveStrategy from "./IMoveStrategy"; export default interface IMove { moveStrategy: IMoveStrategy; - move(number: number): void; + move(): void; } diff --git a/src/Interfaces/IMoveStrategy.ts b/src/Interfaces/IMoveStrategy.ts index 12ccd7b..ef24c75 100644 --- a/src/Interfaces/IMoveStrategy.ts +++ b/src/Interfaces/IMoveStrategy.ts @@ -1,4 +1,4 @@ export default interface IMoveStrategy { speed: number; - move(direction: number): void; + move(): void; } diff --git a/src/Strategies/AttackStrategyOrangeShip.ts b/src/Strategies/AttackStrategyOrangeShip.ts index fed161d..3b7c480 100644 --- a/src/Strategies/AttackStrategyOrangeShip.ts +++ b/src/Strategies/AttackStrategyOrangeShip.ts @@ -1,4 +1,4 @@ -import { Point, Sprite } from "pixi.js"; +import { Point, Sprite, Texture } from "pixi.js"; import IAttackStrategy from "../Interfaces/IAttackStrategy"; import Game from "../Game"; import Bullet from "../objects/Bullet"; @@ -6,15 +6,20 @@ import BulletPool from "../Helpers/BulletPool"; import { Direction } from "../Helpers/Direction"; export default class AttackStrategyOrangeShip implements IAttackStrategy { - bulletSpritePath: string = "assets/shots/orange_shot.png"; + bulletSpriteName: string = "orange_shot.png"; bulletPoint: Point = new Point(-7, -35); bulletSpeed: number = 3; bulletDamage: number = 50; fireInterval: number = 300; attack(): void { - const bullet = BulletPool.Instance.getBulletFromPool(); - this.initializeBullet(bullet); + if (Game.Instance.inputHandler.isKeyDown(" ")) { + if (Game.Instance.player.canAttack()) { + Game.Instance.player.fireIntervalControl.updateLastFireTime(this.fireInterval); + const bullet = BulletPool.Instance.getBulletFromPool(); + this.initializeBullet(bullet); + } + } } initializeBullet(bullet: Bullet): void { @@ -23,6 +28,12 @@ export default class AttackStrategyOrangeShip implements IAttackStrategy { Game.Instance.player.ship.position.y + this.bulletPoint.y, ); - bullet.initialize(Sprite.from(this.bulletSpritePath), point, Direction.Up, this.bulletSpeed, this.bulletDamage); + bullet.initialize( + new Sprite(Texture.from(this.bulletSpriteName)), + point, + Direction.Up, + this.bulletSpeed, + this.bulletDamage, + ); } } diff --git a/src/Strategies/MoveStrategyEnemyWeakShip.ts b/src/Strategies/MoveStrategyEnemyWeakShip.ts new file mode 100644 index 0000000..28d6362 --- /dev/null +++ b/src/Strategies/MoveStrategyEnemyWeakShip.ts @@ -0,0 +1,32 @@ +import Game from "../Game"; +import { Direction } from "../Helpers/Direction"; +import IMoveStrategy from "../Interfaces/IMoveStrategy"; +import { EnemyShipWeak } from "../objects/ships/EnemyShipWeak"; + +export class MoveStrategyEnemyWeakShip implements IMoveStrategy { + speed: number = 1; + enemyShipWeak: EnemyShipWeak; + direction: number = Direction.Right; + screenWidth: number; + + constructor(enemyShipWeak: EnemyShipWeak) { + this.enemyShipWeak = enemyShipWeak; + this.screenWidth = Game.Instance.world.width; + } + + move(): void { + if (this.direction === Direction.Right) { + this.enemyShipWeak.position.x += this.speed * Direction.Right; + if (this.enemyShipWeak.position.x > this.screenWidth - this.enemyShipWeak.width) { + this.enemyShipWeak.position.x = this.screenWidth - this.enemyShipWeak.width; + this.direction = Direction.Left; + } + } else { + this.enemyShipWeak.position.x += this.speed * Direction.Left; + if (this.enemyShipWeak.position.x < this.enemyShipWeak.width) { + this.enemyShipWeak.position.x = this.enemyShipWeak.width; + this.direction = Direction.Right; + } + } + } +} diff --git a/src/Strategies/MoveStrategyOrangeShip.ts b/src/Strategies/MoveStrategyOrangeShip.ts index 84d8861..e33fefd 100644 --- a/src/Strategies/MoveStrategyOrangeShip.ts +++ b/src/Strategies/MoveStrategyOrangeShip.ts @@ -1,4 +1,5 @@ import Game from "../Game"; +import { Direction } from "../Helpers/Direction"; import IMoveStrategy from "../Interfaces/IMoveStrategy"; export default class MoveStrategyOrangeShip implements IMoveStrategy { @@ -8,7 +9,14 @@ export default class MoveStrategyOrangeShip implements IMoveStrategy { this.speed = 5; } - move(direction: number): void { - Game.Instance.player.ship.position.x += this.speed * direction; + move(): void { + if (Game.Instance.inputHandler.right()) { + Game.Instance.player.ship.position.x += this.speed * Direction.Right; + Game.Instance.player.ship.clampPositionToScreen(); + } + if (Game.Instance.inputHandler.left()) { + Game.Instance.player.ship.position.x += this.speed * Direction.Left; + Game.Instance.player.ship.clampPositionToScreen(); + } } } diff --git a/src/core/EnemySpawner.ts b/src/core/EnemySpawner.ts new file mode 100644 index 0000000..8c2fa36 --- /dev/null +++ b/src/core/EnemySpawner.ts @@ -0,0 +1,15 @@ +import Game from "../Game"; +import { EnemyShipWeak } from "../objects/ships/EnemyShipWeak"; + +export class EnemySpawner { + enemyShip: EnemyShipWeak; + + constructor() { + this.enemyShip = new EnemyShipWeak(); + Game.Instance.app.ticker.add(this.gameLoop.bind(this)); + } + + gameLoop() { + this.enemyShip.move(); + } +} diff --git a/src/core/FireIntervalControl.ts b/src/core/FireIntervalControl.ts index 61cda27..ca852c4 100644 --- a/src/core/FireIntervalControl.ts +++ b/src/core/FireIntervalControl.ts @@ -1,3 +1,5 @@ +import Game from "../Game"; + export default class FireIntervalControl { private _lastFireTime: number; @@ -13,7 +15,8 @@ export default class FireIntervalControl { this._lastFireTime = 0; } - updateLastFireTime(newLastFireTime: number): void { - this._lastFireTime = newLastFireTime; + updateLastFireTime(fireInterval: number): void { + const appTime = Game.Instance.app.ticker.lastTime; + this._lastFireTime = appTime + fireInterval; } } diff --git a/src/core/Player.ts b/src/core/Player.ts index 6669eb6..a9b42ce 100644 --- a/src/core/Player.ts +++ b/src/core/Player.ts @@ -1,40 +1,27 @@ import { Ship } from "../objects/ships/Ship"; -import FireIntervalControl from "./FireIntervalControl"; import OrangeShip from "../objects/ships/OrangeShip"; -import InputHandler from "./InputHandler"; import Game from "../Game"; -import { Direction } from "../Helpers/Direction"; +import FireIntervalControl from "./FireIntervalControl"; export class Player { ship: Ship; fireIntervalControl: FireIntervalControl; - inputHandler: InputHandler; constructor() { this.ship = new OrangeShip(); this.fireIntervalControl = new FireIntervalControl(); - this.inputHandler = new InputHandler(); - Game.Instance.app.ticker.add(this.gameLoop.bind(this)); } gameLoop() { - if (this.inputHandler.right()) { - this.ship.clampPositionToScreen(); - this.ship.move(Direction.Right); - } - - if (this.inputHandler.left()) { - this.ship.clampPositionToScreen(); - this.ship.move(Direction.Left); - } + this.ship.move(); + this.ship.attack(); + } - if (this.inputHandler.isKeyDown(" ")) { - if (Game.Instance.app.ticker.lastTime > this.fireIntervalControl.getLastFireTime()) { - const appTime = Game.Instance.app.ticker.lastTime; - this.fireIntervalControl.updateLastFireTime(appTime + this.ship.getFireInterval()); - this.ship.attack(); - } + canAttack(): boolean { + if (Game.Instance.app.ticker.lastTime > this.fireIntervalControl.getLastFireTime()) { + return true; } + return false; } } diff --git a/src/core/World.ts b/src/core/World.ts index c7ee0f4..43be158 100644 --- a/src/core/World.ts +++ b/src/core/World.ts @@ -1,9 +1,9 @@ -import { Sprite } from "pixi.js"; +import { Sprite, Texture } from "pixi.js"; import GameObject from "./GameObject"; export default class World extends GameObject { constructor() { super(); - this.setSprite(Sprite.from("./assets/worlds/pink_galaxy.png")); + this.setSprite(new Sprite(Texture.from("background.png"))); } } diff --git a/src/index.ts b/src/index.ts index 0b02a0b..231a975 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import "./style.css"; -import { Application /*, Assets*/ } from "pixi.js"; +import { Application, Assets } from "pixi.js"; import { gameOptions } from "./gameConfig"; import Game from "./Game"; @@ -18,7 +18,7 @@ const app = new Application({ }); window.onload = async (): Promise => { - //await loadGameAssets(); + await loadGameAssets(); document.body.appendChild(app.view); @@ -26,7 +26,7 @@ window.onload = async (): Promise => { new Game(app); }; -/* + async function loadGameAssets(): Promise { const manifest = { bundles: [ @@ -34,17 +34,8 @@ async function loadGameAssets(): Promise { name: "assets", assets: [ { - name: "bird", - srcs: "./assets/simpleSpriteSheet.json", - }, - ], - }, - { - name: "pixie", - assets: [ - { - name: "pixie", - srcs: "./assets/spine-assets/pixie.json", + name: "assets", + srcs: "./assets/spritesheet.json", }, ], }, @@ -52,9 +43,9 @@ async function loadGameAssets(): Promise { }; await Assets.init({ manifest }); - await Assets.loadBundle(["bird", "pixie"]); + await Assets.loadBundle(["assets"]); } -*/ + function resizeCanvas(): void { const resize = () => { app.renderer.resize(window.innerWidth, window.innerHeight); diff --git a/src/objects/ships/EnemyShipWeak.ts b/src/objects/ships/EnemyShipWeak.ts new file mode 100644 index 0000000..516102c --- /dev/null +++ b/src/objects/ships/EnemyShipWeak.ts @@ -0,0 +1,30 @@ +import { Sprite, Texture } from "pixi.js"; +import { Ship } from "./Ship"; +import { MoveStrategyEnemyWeakShip } from "../../Strategies/MoveStrategyEnemyWeakShip"; + +export class EnemyShipWeak extends Ship { + constructor() { + super(); + this.health = 100; + this.setVisual(); + this.setStrategies(); + } + attack(): void { + throw new Error("Method not implemented."); + } + move(): void { + this.moveStrategy.move(); + } + getHit(damage: number): void { + this.health -= damage; + } + + setStrategies() { + this.moveStrategy = new MoveStrategyEnemyWeakShip(this); + } + setVisual() { + this.setSprite(new Sprite(Texture.from("enemy_ship_weak.png"))); + this.sprite.anchor.set(0.5, 0.5); + this.position.set(400, 50); + } +} diff --git a/src/objects/ships/OrangeShip.ts b/src/objects/ships/OrangeShip.ts index 1e7c000..caf0ad2 100644 --- a/src/objects/ships/OrangeShip.ts +++ b/src/objects/ships/OrangeShip.ts @@ -1,4 +1,4 @@ -import { Sprite } from "pixi.js"; +import { Sprite, Texture } from "pixi.js"; import { Ship } from "./Ship"; import AttackStrategyOrangeShip from "../../Strategies/AttackStrategyOrangeShip"; import MoveStrategyOrangeShip from "../../Strategies/MoveStrategyOrangeShip"; @@ -16,15 +16,15 @@ export default class OrangeAttackShip extends Ship { getFireInterval(): number { return this.attackStrategy.fireInterval; } - move(number: number): void { - this.moveStrategy.move(number); + move(): void { + this.moveStrategy.move(); } getHit(damage: number): void { this.health -= damage; } setVisual() { - this.setSprite(Sprite.from("assets/ships/orange_attack_ship.png")); + this.setSprite(new Sprite(Texture.from("orange_ship.png"))); this.sprite.anchor.set(0.5, 0.5); this.position.set(400, 500); } diff --git a/src/objects/ships/Ship.ts b/src/objects/ships/Ship.ts index 4a8edbc..9be8c59 100644 --- a/src/objects/ships/Ship.ts +++ b/src/objects/ships/Ship.ts @@ -15,7 +15,6 @@ export abstract class Ship extends GameObject implements IAttack, IMove, IHittab } abstract attack(): void; - abstract getFireInterval(): number; - abstract move(number: number): void; + abstract move(): void; abstract getHit(damage: number): void; }