From 11d39542a8634087240603370875a69a4c185f0c Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Fri, 31 May 2019 10:57:18 -0700 Subject: [PATCH] started on scoring section --- content/pong/scoring/_index.md | 156 +++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 content/pong/scoring/_index.md diff --git a/content/pong/scoring/_index.md b/content/pong/scoring/_index.md new file mode 100644 index 0000000..e47edb8 --- /dev/null +++ b/content/pong/scoring/_index.md @@ -0,0 +1,156 @@ +--- +title: "Scoring" +date: 2019-05-30T16:08:54-07:00 +weight: 1000 +--- + +In Pong, your opponent scores a point by getting the ball behind your paddle. + +There's a couple of things we need to sort out here: 1) tracking and displaying each player's score, and 2) reacting appropriately when a ball collides with a goal (side) boundary. + +Let's start by creating a ScoreComponent. + +```ts +import { Component } from "encompass-ecs"; + +export class ScoreComponent extends Component { + public score: number; + public player_one: boolean; +} +``` + +And let's have a new collision type. + +```ts +export enum CollisionType { + ball, + goal, + paddle, + wall, +} +``` + +We'll need a new BallGoalCollisionMessage: + +```ts +import { Entity, Message } from "encompass-ecs"; + +export class BallGoalCollisionMessage extends Message { + public ball_entity: Entity; + public goal_entity: Entity; +} +``` + +And some dispatch logic in the CollisionDispatchEngine: + +```ts +... + +switch (collision_message.collision_type_one) { + case CollisionType.ball: + switch (collision_message.collision_type_two) { + case CollisionType.goal: { + const message = this.emit_message(BallGoalCollisionMessage); + message.ball_entity = collision_message.entity_one; + message.goal_entity = collision_message.entity_two; + break; + } + +... +``` + +And a new BallGoalCollisionEngine: + +```ts +import { Engine, Mutates, Reads } from "encompass-ecs"; +import { ScoreComponent } from "game/components/score"; +import { BallGoalCollisionMessage } from "game/messages/collisions/ball_goal"; +import { World } from "lua-lib/bump"; + +@Reads(BallGoalCollisionMessage) +@Mutates(ScoreComponent) +export class BallGoalCollisionEngine extends Engine { + private collision_world: World; + + public initialize(collision_world: World) { + this.collision_world = collision_world; + } + + public update() { + for (const message of this.read_messages(BallGoalCollisionMessage).values()) { + const score_component = this.make_mutable(message.goal_entity.get_component(ScoreComponent)); + score_component.score += 1; + + message.ball_entity.destroy(); + this.collision_world.remove(message.ball_entity); + } + } +} +``` + +I've decided we should just attach the ScoreComponent directly to the goal entity for simplicity. + +We'll need a way to create our goal entities now. + +Let's have a new GoalSpawnMessage: + +```ts +import { Message } from "encompass-ecs"; + +export class GoalSpawnMessage extends Message { + public x: number; + public y: number; + public width: number; + public height: number; + public player_one: boolean; +} +``` + +And a new GoalSpawner: + +```ts +import { 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 { ScoreComponent } from "game/components/score"; +import { GoalSpawnMessage } from "game/messages/goal_spawn"; +import { World } from "lua-lib/bump"; + +export class GoalSpawner extends Spawner { + public spawn_message_type = GoalSpawnMessage; + + private collision_world: World; + + public initialize(collision_world: World) { + this.collision_world = collision_world; + } + + public spawn(message: GoalSpawnMessage) { + const entity = this.create_entity(); + + const score_component = entity.add_component(ScoreComponent); + score_component.score = 0; + score_component.player_one = message.player_one; + + 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.goal ]; + + this.collision_world.add( + entity, + message.x - message.width * 0.5, + message.y - message.height * 0.5, + message.width, + message.height + ); + } +} +```