diff --git a/content/pong/ball/bouncing/boundaries.md b/content/pong/ball/bouncing/boundaries.md new file mode 100644 index 0000000..2f7ffcc --- /dev/null +++ b/content/pong/ball/bouncing/boundaries.md @@ -0,0 +1,95 @@ +--- +title: "Boundaries" +date: 2019-05-29T11:05:16-07:00 +weight: 900 +--- + +Now that we have bouncing capabilities, we can add them easily to other entities. Let's make boundary boxes that make the ball bounce off the sides of the game area. + +**PongFE/Messages/BoundarySpawnMessage.cs**: + +```cs +using Encompass; +using MoonTools.Structs; + +namespace PongFE.Messages +{ + public struct BoundarySpawnMessage : IMessage + { + public Position2D Position { get; } + public int Width { get; } + public int Height { get; } + + public BoundarySpawnMessage(Position2D position, int width, int height) + { + Position = position; + Width = width; + Height = height; + } + } +} +``` + +**PongFE/Engines/BoundarySpawner.cs**: + +```cs +using Encompass; +using PongFE.Components; +using PongFE.Messages; + +namespace PongFE.Spawners +{ + public class BoundarySpawner : Spawner + { + protected override void Spawn(BoundarySpawnMessage message) + { + var entity = CreateEntity(); + + AddComponent(entity, new PositionComponent(message.Position)); + AddComponent(entity, new CollisionComponent(new MoonTools.Bonk.Rectangle(0, 0, message.Width, message.Height))); + AddComponent(entity, new CanCauseBounceComponent()); + } + } +} +``` + +Now we can create the boundary entities by sending messages with WorldBuilder. + +**PongFEGame.cs** + +```cs + ... + + WorldBuilder.AddEngine(new BoundarySpawner()); + + ... + + // top boundary + WorldBuilder.SendMessage( + new BoundarySpawnMessage( + new MoonTools.Structs.Position2D(0, -6), + 1280, + 6 + ) + ); + + // right boundary + WorldBuilder.SendMessage( + new BoundarySpawnMessage( + new MoonTools.Structs.Position2D(1280, 0), + 6, + 720 + ) + ); + + // bottom boundary + WorldBuilder.SendMessage( + new BoundarySpawnMessage( + new MoonTools.Structs.Position2D(0, 720), + 1280, + 6 + ) + ); +``` + +Notice that we didn't have to write any new game logic to add boundaries to our game. This is the power of modular composition using ECS. diff --git a/content/pong/ball/bouncing/spawners.md b/content/pong/ball/bouncing/spawners.md deleted file mode 100644 index 66570c4..0000000 --- a/content/pong/ball/bouncing/spawners.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -title: "Spawners" -date: 2019-05-29T11:05:16-07:00 -weight: 900 ---- - -Our Entities are getting a bit more complex now with the addition of BoundingBoxComponents and CollisionTypeComponents. - -I think we should create Spawners for each of our game entities. - -This will be pretty straightforward. Just decide which parameters we need to create our entities, and add the proper components with those parameters. - -### Ball - -In **game/messages/ball_spawn.ts**: - -```ts -import { Message } from "encompass-ecs"; - -export class BallSpawnMessage extends Message { - public x: number; - public y: number; - public size: number; - public x_velocity: number; - public y_velocity: number; -} -``` - -In **game/engines/spawners/ball.ts**: - -```ts -import { Reads, Spawner } from "encompass-ecs"; -import { BoundingBoxComponent } from "game/components/bounding_box"; -import { CanvasComponent } from "game/components/canvas"; -import { CollisionType, CollisionTypesComponent } from "game/components/collision_types"; -import { PositionComponent } from "game/components/position"; -import { VelocityComponent } from "game/components/velocity"; -import { BallSpawnMessage } from "game/messages/ball_spawn"; -import { World } from "lua-lib/bump"; - -@Reads(BallSpawnMessage) -export class BallSpawner extends Spawner { - public collision_world: World; - - public initialize(collision_world: World) { - this.collision_world = collision_world; - } - - public spawn(message: BallSpawnMessage) { - const ball_entity = this.create_entity(); - - const ball_position_component = ball_entity.add_component(PositionComponent); - ball_position_component.x = message.x; - ball_position_component.y = message.y; - - const ball_canvas = love.graphics.newCanvas(message.size, message.size); - love.graphics.setCanvas(ball_canvas); - love.graphics.setBlendMode("alpha"); - love.graphics.setColor(1, 1, 1, 1); - love.graphics.rectangle("fill", 0, 0, message.size, message.size); - love.graphics.setCanvas(); - - const ball_canvas_component = ball_entity.add_component(CanvasComponent); - ball_canvas_component.canvas = ball_canvas; - ball_canvas_component.x_scale = 1; - ball_canvas_component.y_scale = 1; - - const velocity_component = ball_entity.add_component(VelocityComponent); - velocity_component.x = message.x_velocity; - velocity_component.y = message.y_velocity; - - const boundaries_component = ball_entity.add_component(BoundingBoxComponent); - boundaries_component.width = message.size; - boundaries_component.height = message.size; - - const collision_types_component = ball_entity.add_component(CollisionTypesComponent); - collision_types_component.collision_types = [ CollisionType.ball ]; - - this.collision_world.add(ball_entity, message.x, message.y, message.size, message.size); - } -} -``` - -### Game Boundary - -In **game/messages/game_boundary_spawn.ts**: - -```ts -import { Message } from "encompass-ecs"; - -export class GameBoundarySpawnMessage extends Message { - public x: number; - public y: number; - public width: number; - public height: number; -} -``` - -In **game/spawners/game_boundary.ts**: - -```ts -import { Reads, Spawner } from "encompass-ecs"; -import { BoundingBoxComponent } from "game/components/bounding_box"; -import { CollisionType, CollisionTypesComponent } from "game/components/collision_types"; -import { PositionComponent } from "game/components/position"; -import { GameBoundarySpawnMessage } from "game/messages/game_boundary_spawn"; -import { World } from "lua-lib/bump"; - -@Reads(GameBoundarySpawnMessage) -export class GameBoundarySpawner extends Spawner { - private collision_world: World; - - public initialize(collision_world: World) { - this.collision_world = collision_world; - } - - public spawn(message: GameBoundarySpawnMessage) { - const entity = this.create_entity(); - - const boundaries = entity.add_component(BoundingBoxComponent); - boundaries.width = message.width; - boundaries.height = message.height; - - const position = entity.add_component(PositionComponent); - position.x = message.x; - position.y = message.y; - - const collision_types_component = entity.add_component(CollisionTypesComponent); - collision_types_component.collision_types = [ CollisionType.wall ]; - - this.collision_world.add( - entity, - message.x - message.width * 0.5, - message.y - message.height * 0.5, - message.width, - message.height - ); - } -} -``` - -### Paddle - -In **game/messages/paddle_spawn.ts**: - -```ts -import { Message } from "encompass-ecs"; - -export class PaddleSpawnMessage extends Message { - public x: number; - public y: number; - public width: number; - public height: number; - public move_speed: number; -} -``` - -In **game/spawners/paddle.ts**: - -```ts -import { Reads, Spawner } from "encompass-ecs"; -import { BoundingBoxComponent } from "game/components/bounding_box"; -import { CanvasComponent } from "game/components/canvas"; -import { CollisionType, CollisionTypesComponent } from "game/components/collision_types"; -import { PaddleMoveSpeedComponent } from "game/components/paddle_move_speed"; -import { PlayerOneComponent } from "game/components/player_one"; -import { PositionComponent } from "game/components/position"; -import { PaddleSpawnMessage } from "game/messages/paddle_spawn"; -import { World } from "lua-lib/bump"; - -@Reads(PaddleSpawnMessage) -export class PaddleSpawner extends Spawner { - private collision_world: World; - - public initialize(collision_world: World) { - this.collision_world = collision_world; - } - - protected spawn(message: PaddleSpawnMessage) { - const paddle_entity = this.create_entity(); - - paddle_entity.add_component(PlayerOneComponent); - - const width = message.width; - const height = message.height; - - const paddle_canvas = love.graphics.newCanvas(width, height); - love.graphics.setCanvas(paddle_canvas); - love.graphics.setBlendMode("alpha"); - love.graphics.setColor(1, 1, 1, 1); - love.graphics.rectangle("fill", 0, 0, width, height); - love.graphics.setCanvas(); - - const canvas_component = paddle_entity.add_component(CanvasComponent); - canvas_component.canvas = paddle_canvas; - canvas_component.x_scale = 1; - canvas_component.y_scale = 1; - - const position_component = paddle_entity.add_component(PositionComponent); - position_component.x = message.x; - position_component.y = message.y; - - const move_speed_component = paddle_entity.add_component(PaddleMoveSpeedComponent); - move_speed_component.y = message.move_speed; - - const paddle_boundaries = paddle_entity.add_component(BoundingBoxComponent); - paddle_boundaries.width = width; - paddle_boundaries.height = height; - - const collision_types_component = paddle_entity.add_component(CollisionTypesComponent); - collision_types_component.collision_types = [ CollisionType.paddle ]; - - this.collision_world.add( - paddle_entity, - message.x - width * 0.5, - message.y - height * 0.5, - width, - height - ); - } -} -```