diff --git a/other/electrician/files/classdef.js b/other/electrician/files/classdef.js index 303cf65..c24caba 100644 --- a/other/electrician/files/classdef.js +++ b/other/electrician/files/classdef.js @@ -75,6 +75,8 @@ class Ladder { class Building { + static GROUND_FLOOR_LEVEL = 589; + constructor(){ this.ladder = new Ladder(); this.floors = []; @@ -84,28 +86,8 @@ class Building { this.rightPowerLine = new PowerLine(); } - init(floorCount, physics){ + init(physics){ this.ladder.init(physics); - - const floorBuilder1 = new FloorBuilder(); - this.floors.push(floorBuilder1.withName('attic').withBottomConnector(3).withBottomConnector(11) - .withCeilingConnector(5).withCeilingConnector(25).withBottomConnector(28).build()); - const floorBuilder2 = new FloorBuilder(); - this.floors.push(floorBuilder2.withName('living room').withCeilingConnector(2).withCeilingConnector(29) - .withLampInCenter().withTVInCenterLeft().build()); - const kitchenBuilder = new FloorBuilder(); - this.floors.push(kitchenBuilder.withName('kitchen').withFridgeOnLeft().withLampInCenter().withKitchenSegmentOnRight().build()); - - this.floors.forEach(floor => floor.init(physics)); - this.floors.forEach(floor => floor.calculateFloorLevel()); - - const connectionPointsCounts = [2, 6, 5]; - this.wires = this.floors.map((floor, i) => { - const aboveFloor = this.floors[i] || null; - const belowFloor = this.floors[i - 1] || null; - return new Wire(i, physics, belowFloor, aboveFloor, connectionPointsCounts[i]); - }); - this.leftPowerLine.init(physics, 'left'); this.rightPowerLine.init(physics, 'right'); } @@ -340,64 +322,6 @@ class Rat extends Enemy{ } } -class Creator { - static create3storeBuilding(physics) { - const building = new Building(); - building.init(3, physics); - building.includeWiresInInfoFrame(); - - const atticCeilingLevel = 104; - const livingRoomCeilingLevel = 328 - Floor.HEIGHT / 2; - const kitchenLevel = 438; - const groundFloorLevel = 589; //under kitchen - - const ratsData = [ - { id: 1, active: true, y: groundFloorLevel }, - { id: 2, active: true, y: groundFloorLevel, minX: Floor.WIDTH / 2, maxX: 2 * Floor.WIDTH / 3, velocity: { x : 3} }, - { id: 3, active: true, y: atticCeilingLevel, minX: Floor.WIDTH / 3 + 30, maxX: 1.15*Floor.WIDTH, wireId: 0 }, - { id: 4, active: true, y: kitchenLevel, velocity: { x: 0.7 }, wireId: 2}, - { id: 5, active: true, y: groundFloorLevel, velocity: { x: 1.4 } }, - { id: 6, active: true, y: livingRoomCeilingLevel, minX: 2 * Floor.WIDTH / 4, maxX: 1.15*Floor.WIDTH, velocity: { x: 1.4 }, wireId: 1 }, - { id: 7, active: true, y: livingRoomCeilingLevel, minX: 2 * Ladder.WIDTH, velocity: { x: 0.85}, wireId: 1 }, - ]; - - const batsData = [ - { id: 0, active: true, speed: -0.017 }, - { id: 1, active: true, currentAngle: Math.PI / 2, /*speed: 0.001*/ } - ]; - - const createEnemy = (EnemyClass, data, physics, positionAdjustment = 0) => { - const enemy = new EnemyClass(data.id); - enemy.active = data.active; - const y = EnemyClass === Rat ? data.y : 555 + 7 * data.id + positionAdjustment; - enemy.init(physics, y); - - Object.assign(enemy, { - minX: data.minX || enemy.minX, - maxX: data.maxX || enemy.maxX, - angularSpeed: data.speed || enemy.angularSpeed, - currentAngle: data.currentAngle || enemy.currentAngle, - wireId: EnemyClass === Rat ? data.wireId : undefined - }); - - if (EnemyClass === Bat) { - enemy.centerX = Constants.SCREEN_WIDTH / 2 + 50 - 39 * data.id; - } - - if (data.velocity) enemy.sprite.velocity = data.velocity; - - return enemy; - }; - - const rats = ratsData.map(data => createEnemy(Rat, data, physics)); - const bats = batsData.map(data => createEnemy(Bat, data, physics)); - - building.enemies.push(...rats, ...bats); - - return building; - } -} - class FloorBuilder { constructor(){ diff --git a/other/electrician/files/creators.js b/other/electrician/files/creators.js new file mode 100644 index 0000000..ad9ce96 --- /dev/null +++ b/other/electrician/files/creators.js @@ -0,0 +1,78 @@ +class Creator { + static create3storeBuilding(physics) { + let building = new Building(); + building.init(physics); // Initializes ladder and power lines + + const floorBuilder1 = new FloorBuilder(); + building.floors.push(floorBuilder1.withName('attic').withBottomConnector(3).withBottomConnector(11) + .withCeilingConnector(5).withCeilingConnector(25).withBottomConnector(28).build()); + + const floorBuilder2 = new FloorBuilder(); + building.floors.push(floorBuilder2.withName('living room').withCeilingConnector(2).withCeilingConnector(29) + .withLampInCenter().withTVInCenterLeft().build()); + + const kitchenBuilder = new FloorBuilder(); + building.floors.push(kitchenBuilder.withName('kitchen').withFridgeOnLeft().withLampInCenter().withKitchenSegmentOnRight().build()); + + building.floors.forEach(floor => floor.init(physics)); + building.floors.forEach(floor => floor.calculateFloorLevel()); + + const connectionPointsCounts = [2, 6, 5]; + building.wires = building.floors.map((floor, index) => { + const aboveFloor = building.floors[index] || null; + const belowFloor = building.floors[index - 1] || null; + return new Wire(index, physics, belowFloor, aboveFloor, connectionPointsCounts[index]); + }); + + building.includeWiresInInfoFrame(); + + const atticCeilingLevel = 104; + const livingRoomCeilingLevel = 328 - Floor.HEIGHT / 2; + const kitchenLevel = 438; + + const ratsData = [ + { id: 1, active: true, y: Building.GROUND_FLOOR_LEVEL }, + { id: 2, active: true, y: Building.GROUND_FLOOR_LEVEL, minX: Floor.WIDTH / 2, maxX: 2 * Floor.WIDTH / 3, velocity: { x : 3} }, + { id: 3, active: true, y: Building.GROUND_FLOOR_LEVEL, velocity: { x: 1.4 } }, + { id: 4, active: true, y: kitchenLevel, velocity: { x: 0.7 }, wireId: 2}, + { id: 5, active: true, y: livingRoomCeilingLevel, minX: 2 * Floor.WIDTH / 4, maxX: 1.15*Floor.WIDTH, velocity: { x: 1.4 }, wireId: 1 }, + { id: 6, active: true, y: livingRoomCeilingLevel, minX: 2 * Ladder.WIDTH, velocity: { x: 0.85}, wireId: 1 }, + { id: 7, active: true, y: atticCeilingLevel, minX: Floor.WIDTH / 3 + 30, maxX: 1.15*Floor.WIDTH, wireId: 0 } + ]; + + const batsData = [ + { id: 0, active: true, speed: -0.017 }, + { id: 1, active: true, currentAngle: Math.PI / 2, /*speed: 0.001*/ } + ]; + + const createEnemy = (EnemyClass, data, physics, positionAdjustment = 0) => { + const enemy = new EnemyClass(data.id); + enemy.active = data.active; + const y = EnemyClass === Rat ? data.y : 555 + 7 * data.id + positionAdjustment; + enemy.init(physics, y); + + Object.assign(enemy, { + minX: data.minX || enemy.minX, + maxX: data.maxX || enemy.maxX, + angularSpeed: data.speed || enemy.angularSpeed, + currentAngle: data.currentAngle || enemy.currentAngle, + wireId: EnemyClass === Rat ? data.wireId : undefined + }); + + if (EnemyClass === Bat) { + enemy.centerX = Constants.SCREEN_WIDTH / 2 + 50 - 39 * data.id; + } + + if (data.velocity) enemy.sprite.velocity = data.velocity; + + return enemy; + }; + + const rats = ratsData.map(data => createEnemy(Rat, data, physics)); + const bats = batsData.map(data => createEnemy(Bat, data, physics)); + + building.enemies.push(...rats, ...bats); + + return building; + } +} diff --git a/other/electrician/files/electrician.js b/other/electrician/files/electrician.js index 52c37d3..478bab6 100644 --- a/other/electrician/files/electrician.js +++ b/other/electrician/files/electrician.js @@ -1,220 +1,3 @@ -class MainScene extends Phaser.Scene { - constructor() { - super({ key: 'MainScene' }); - this.spriteCanJump = true; - } - - preload() { - Floor.WIDTH = 617;//ladderTexture.getSourceImage().width; - Floor.HEIGHT = 110;//ladderTexture.getSourceImage().height; - console.log('Floor height = ' + Floor.HEIGHT); - - this.load.image('sprite', 'files/electrician.png'); - for (let i = 1; i <= 8; i++) { - this.load.image(`rat${i}`, 'files/rat.png'); - } - this.load.image('bat', 'files/bat.png'); - - this.load.image('ladder', 'files/ladder.png'); - - this.load.image('floor0', 'files/attic.png'); - const ladderTexture = this.textures.get('floor0'); - - this.load.image('floor1', 'files/livingRoom.png'); - this.load.image('floor2', 'files/kitchen.png'); - - this.load.image('power-line-left', 'files/powerlineL.png'); - this.load.image('power-line-right', 'files/powerlineR.png'); - - this.load.image('empty-wire-section', 'files/wire.png'); - this.load.image('wire-section', 'files/wire.png'); - this.load.image('wire-section-up', 'files/wireUp.png'); - this.load.image('wire-section-down', 'files/wireDown.png'); - } - - create() { - this.physics.world.setBounds(0, 0, 800, 600); - - this.building = Creator.create3storeBuilding(this.physics); - - this.player = this.physics.add.sprite(100, 400, 'sprite'); - this.player.setCollideWorldBounds(true); - - this.cursors = this.input.keyboard.createCursorKeys(); - } - - update() { - this.handlePlayerMovement(); - this.handleEnemyMovement(); - this.checkCollisions(); - this.conditionalFallDown(); - } - - jump(direction) { - if (!this.spriteCanJump) return; - - this.spriteCanJump = false; - const jumpHeight = 45; - const duration = 750; - - const jumpTween = { - targets: this.player, - y: this.player.y - jumpHeight, // Move up - duration: duration / 2, // Up for half the duration - ease: 'Linear', - onComplete: () => { - - const comeDownTween = { - targets: this.player, - y: this.player.y + jumpHeight, // Move down - duration: duration / 2, - ease: 'Linear', - onComplete: () => { - // Re-enable jumping after 1 second - this.spriteCanJump = true; - } - }; - this.tweens.add(comeDownTween); - } - } - - this.tweens.add(jumpTween); - - if (direction === 'left') { - this.player.setVelocityX(-160); - } else if (direction === 'right') { - this.player.setVelocityX(160); - } else { - this.player.setVelocityX(0); // No horizontal movement if just jumping - } - } - - checkCollisions(){ - const collidingEnemy = this.building.enemies.find(e => e.collide(this.player) != 0); - - if (collidingEnemy != null){ - if (collidingEnemy instanceof Rat) this.player.x += 15 * collidingEnemy.collide(this.player); - else if (collidingEnemy instanceof Bat) { - var audioBing = new Audio('files/bing.m4a'); - audioBing.play(); - this.player.y += Math.abs(29 * collidingEnemy.collide(this.player)); - } - } - } - - conditionalFallDown(){ - let flrs = "" - - if (this.building.ladder.onLadder(this.player.x)){ - return; //Ladder prevents from falling; - } - - let velocity = 160; - - this.building.floors.forEach(f => { - flrs += " " + f.floorLevel; - - if (f.onFloor(this.player.x, this.player.y) && !this.building.ladder.onLadder(this.player.x)){ - //console.log('Floor met on y= ' + this.player.y); - velocity = 0; //Floor under feet prevents from falling - this.player.spriteCanJump = true; - return; - } - }); - - this.player.setVelocityY(velocity); - //console.log("Fall down y = ", this.player.y, " FloorLevels = " + flrs); - } - - handlePlayerMovement() { - let velocityX = 0; - let velocityY = 0; - - if (this.cursors.left.isDown) { - velocityX = -160; - if (this.cursors.up.isDown) { - this.jump('left'); - } - } else if (this.cursors.right.isDown) { - velocityX = 160; - if (this.cursors.up.isDown) { - this.jump('right'); - } - } - - if (velocityX === 0 && this.building.ladder.onLadder(this.player.x)) { - if (this.cursors.up.isDown) { - velocityY = -160; - } else if (this.cursors.down.isDown) { - velocityY = 160; - } - } - - this.player.setVelocityX(velocityX); - this.player.setVelocityY(velocityY); - - if (this.cursors.space.isDown || this.cursors.shift.isDown){ - let action = WireSlot.WIRE_STRAIGHT; - if (this.cursors.down.isDown) { - action = WireSlot.WIRE_DOWN; - } - else if (this.cursors.up.isDown) { - action = WireSlot.WIRE_UP; - } - - this.building.drawWire(this.player, action); - } - - this.writeFloorInfo(); - } - - handleEnemyMovement(){ - this.building.enemies.filter(e => e.active).forEach(enemy => { - enemy.move(); - if (enemy instanceof Rat){ - if (enemy.wireId === undefined) return; - - const wireId = enemy.wireId; - const wire = this.building.wires[wireId]; - const currentFloor = this.building.floors[wireId]; - const wireSlotIndexPair = wire.getSlotAtCoordinateX(currentFloor, enemy.sprite.x); - - if (wireSlotIndexPair.slot === WireSlot.WIRE_DOWN){ - if (wire.isConnected()){ - var audioZap = new Audio('files/zap.m4a'); - audioZap.play(); - - enemy.active = false; //Zapped Rat becomes immobile - return; - } - - const slotIndex = wireSlotIndexPair.index; - this.building.wires[wireId].place(currentFloor, enemy.sprite ,WireSlot.EMPTY); - if (this.building.wires[wireId].actualFloorConnections.has(slotIndex)) { - var audioChrup = new Audio('files/chrup.m4a'); - audioChrup.play(); - - this.building.wires[wireId].actualFloorConnections.delete(slotIndex); - } - console.log(`Rat ${enemy.id} bit thru wire ${wireId}.`); - } - } - }); - } - - writeFloorInfo(){ - const floorInfo = document.getElementById('floor-number'); - const realCurrentFloor = this.building.getCurrentFloor(this.player); - let prettyCurrentFloor = this.building.floors.length - realCurrentFloor; - if (Math.abs(this.player.y - 600) < 30){ - prettyCurrentFloor = 0; - } - - let prettyCurrentFloorText = realCurrentFloor < 0 ? ' ' : prettyCurrentFloor; - floorInfo.innerText = `${prettyCurrentFloorText} (${realCurrentFloor})`; - } -} - const config = { type: Phaser.AUTO, width: Constants.SCREEN_WIDTH, @@ -226,7 +9,7 @@ const config = { debug: false } }, - scene: MainScene + scene: Level1Scene }; const game = new Phaser.Game(config); diff --git a/other/electrician/files/electrician.test.js b/other/electrician/files/electrician.test.js index d5d603e..d02ceb0 100644 --- a/other/electrician/files/electrician.test.js +++ b/other/electrician/files/electrician.test.js @@ -62,39 +62,6 @@ describe('Ladder Class', () => { }); }); - test('Building1: should create ladder correctly', () => { - let building; - let mockPhysics; - - mockPhysics = { - add: { - sprite: jest.fn().mockReturnValue({ x: Ladder.WIDTH/2 }) - } - }; - building = new Building(); - building.init(11, mockPhysics); - - expect(building.ladder.sprite.x).toBe(Ladder.WIDTH/2); - expect(building.ladder.onLadder(Ladder.WIDTH - 1)).toBe(true); - expect(building.ladder.onLadder(Ladder.WIDTH + 1)).toBe(false); -}); - -test('Building2: should create floors correctly', () => { - let mockPhysics = { - add: { - sprite: jest.fn().mockReturnValue({ x: 800/2 + Ladder.WIDTH/2 - 20 }) - } - }; - let building = new Building(); - building.init(3, mockPhysics); - - expect(building.floors.length).toBe(3); - - for (let i = 0; i < building.floors; i++){ - console.log(`Floor ${i} level ${building.floors[i].floorLevel}`); - } -}); - describe('Wire Class', () => { let wire; let mockPhysics; diff --git a/other/electrician/files/level1.js b/other/electrician/files/level1.js new file mode 100644 index 0000000..5584d4b --- /dev/null +++ b/other/electrician/files/level1.js @@ -0,0 +1,233 @@ +class LevelScene extends Phaser.Scene { + constructor(levelName) { + super({ key: levelName }); + this.playerCanJump = true; + this.playerFalling = false; + } + + preload() { + Floor.WIDTH = 617;//ladderTexture.getSourceImage().width; + Floor.HEIGHT = 110;//ladderTexture.getSourceImage().height; + console.log('Floor height = ' + Floor.HEIGHT); + + this.load.image('sprite', 'files/electrician.png'); + for (let i = 1; i <= 8; i++) { + this.load.image(`rat${i}`, 'files/rat.png'); + } + this.load.image('bat', 'files/bat.png'); + + this.load.image('ladder', 'files/ladder.png'); + + this.loadFloorImages(); + + //const ladderTexture = this.textures.get('floor0'); + this.load.image('power-line-left', 'files/powerlineL.png'); + this.load.image('power-line-right', 'files/powerlineR.png'); + + this.load.image('empty-wire-section', 'files/wire.png'); + this.load.image('wire-section', 'files/wire.png'); + this.load.image('wire-section-up', 'files/wireUp.png'); + this.load.image('wire-section-down', 'files/wireDown.png'); + } + + loadFloorImages(){ + //abstract + } + + create() { + this.physics.world.setBounds(0, 0, 800, 600); + + this.building = Creator.create3storeBuilding(this.physics); + + this.player = this.physics.add.sprite(100, 400, 'sprite'); + this.player.setCollideWorldBounds(true); + + this.cursors = this.input.keyboard.createCursorKeys(); + } + + update() { + this.handlePlayerMovement(); + this.handleEnemyMovement(); + this.checkCollisions(); + this.conditionalFallDown(); + } + + jump(direction) { + if (!this.playerCanJump || this.playerFalling) return; + + this.playerCanJump = false; + const jumpHeight = 45; + const duration = 750; + + const jumpTween = { + targets: this.player, + y: this.player.y - jumpHeight, // Move up + duration: duration / 2, // Up for half the duration + ease: 'Linear', + onComplete: () => { + + const comeDownTween = { + targets: this.player, + y: this.player.y + jumpHeight, // Move down + duration: duration / 2, + ease: 'Linear', + onComplete: () => { + // Re-enable jumping after 1 second + this.playerCanJump = true; + } + }; + this.tweens.add(comeDownTween); + } + } + + this.tweens.add(jumpTween); + + if (direction === 'left') { + this.player.setVelocityX(-160); + } else if (direction === 'right') { + this.player.setVelocityX(160); + } else { + this.player.setVelocityX(0); // No horizontal movement if just jumping + } + } + + checkCollisions(){ + const collidingEnemy = this.building.enemies.find(e => e.collide(this.player) != 0); + + if (collidingEnemy != null){ + if (collidingEnemy instanceof Rat) this.player.x += 15 * collidingEnemy.collide(this.player); + else if (collidingEnemy instanceof Bat) { + var audioBing = new Audio('files/bing.m4a'); + audioBing.play(); + this.player.y += Math.abs(29 * collidingEnemy.collide(this.player)); + } + } + } + + conditionalFallDown(){ + let flrs = "" + + if (this.building.ladder.onLadder(this.player.x)){ + this.playerFalling = false; + return; //Ladder prevents from falling; + } + + this.playerFalling = true; + let velocity = 160; + + this.building.floors.forEach(f => { + flrs += " " + f.floorLevel; + + if (Building.GROUND_FLOOR_LEVEL - this.player.y <=16.5 || (f.onFloor(this.player.x, this.player.y) && !this.building.ladder.onLadder(this.player.x))){ + //console.log('Floor met on y= ' + this.player.y); + velocity = 0; //Floor under feet prevents from falling + this.playerFalling = false; + return; + } + }); + + this.player.setVelocityY(velocity); + //console.log("Fall down y = ", this.player.y, " FloorLevels = " + flrs); + } + + handlePlayerMovement() { + let velocityX = 0; + let velocityY = 0; + + if (this.cursors.left.isDown) { + velocityX = -160; + if (this.cursors.up.isDown) { + this.jump('left'); + } + } else if (this.cursors.right.isDown) { + velocityX = 160; + if (this.cursors.up.isDown) { + this.jump('right'); + } + } + + if (velocityX === 0 && this.building.ladder.onLadder(this.player.x)) { + if (this.cursors.up.isDown) { + velocityY = -160; + } else if (this.cursors.down.isDown) { + velocityY = 160; + } + } + + this.player.setVelocityX(velocityX); + this.player.setVelocityY(velocityY); + + if (this.cursors.space.isDown || this.cursors.shift.isDown){ + let action = WireSlot.WIRE_STRAIGHT; + if (this.cursors.down.isDown) { + action = WireSlot.WIRE_DOWN; + } + else if (this.cursors.up.isDown) { + action = WireSlot.WIRE_UP; + } + + this.building.drawWire(this.player, action); + } + + this.writeFloorInfo(); + } + + handleEnemyMovement(){ + this.building.enemies.filter(e => e.active).forEach(enemy => { + enemy.move(); + if (enemy instanceof Rat){ + if (enemy.wireId === undefined) return; + + const wireId = enemy.wireId; + const wire = this.building.wires[wireId]; + const currentFloor = this.building.floors[wireId]; + const wireSlotIndexPair = wire.getSlotAtCoordinateX(currentFloor, enemy.sprite.x); + + if (wireSlotIndexPair.slot === WireSlot.WIRE_DOWN){ + if (wire.isConnected()){ + var audioZap = new Audio('files/zap.m4a'); + audioZap.play(); + + enemy.active = false; //Zapped Rat becomes immobile + return; + } + + const slotIndex = wireSlotIndexPair.index; + this.building.wires[wireId].place(currentFloor, enemy.sprite ,WireSlot.EMPTY); + if (this.building.wires[wireId].actualFloorConnections.has(slotIndex)) { + var audioChrup = new Audio('files/chrup.m4a'); + audioChrup.play(); + + this.building.wires[wireId].actualFloorConnections.delete(slotIndex); + } + console.log(`Rat ${enemy.id} bit thru wire ${wireId}.`); + } + } + }); + } + + writeFloorInfo(){ + const floorInfo = document.getElementById('floor-number'); + const realCurrentFloor = this.building.getCurrentFloor(this.player); + let prettyCurrentFloor = this.building.floors.length - realCurrentFloor; + if (Math.abs(this.player.y - 600) < 30){ + prettyCurrentFloor = 0; + } + + let prettyCurrentFloorText = realCurrentFloor < 0 ? ' ' : prettyCurrentFloor; + floorInfo.innerText = `${prettyCurrentFloorText} (${realCurrentFloor})`; + } +} + +class Level1Scene extends LevelScene{ + + constructor() { + super('Level1'); + } + + loadFloorImages(){ + this.load.image('floor0', 'files/attic.png'); + this.load.image('floor1', 'files/livingRoom.png'); + this.load.image('floor2', 'files/kitchen.png'); + } +} diff --git a/other/electrician/index.html b/other/electrician/index.html index 6f67c5f..2465c52 100644 --- a/other/electrician/index.html +++ b/other/electrician/index.html @@ -26,5 +26,7 @@ + +