diff --git a/content/pong/ball/bouncing/collision_dispatch.md b/content/pong/ball/bouncing/collision_dispatch.md index 59db094..1611319 100644 --- a/content/pong/ball/bouncing/collision_dispatch.md +++ b/content/pong/ball/bouncing/collision_dispatch.md @@ -27,7 +27,14 @@ export class CollisionDispatchEngine extends Engine { case CollisionType.ball: switch (collision_message.collision_type_two) { case CollisionType.paddle: { - // an exercise for the reader ;) + const message = this.emit_message(BallPaddleCollisionMessage); + message.ball_entity = collision_message.entity_one; + message.paddle_entity = collision_message.entity_two; + message.ball_new_x = collision_message.entity_one_new_x; + message.ball_new_y = collision_message.entity_one_new_y; + message.normal = collision_message.collision_data.normal; + message.touch = collision_message.collision_data.touch; + break; } case CollisionType.wall: { @@ -46,7 +53,14 @@ export class CollisionDispatchEngine extends Engine { case CollisionType.paddle: { switch (collision_message.collision_type_two) { case CollisionType.wall: { - // another exercise for the reader ;) + const message = this.emit_message(PaddleWallCollisionMessage); + message.paddle_entity = collision_message.entity_one; + message.paddle_new_x = collision_message.entity_one_new_x; + message.paddle_new_y = collision_message.entity_one_new_y; + message.wall_entity = collision_message.entity_two; + message.normal = collision_message.collision_data.normal; + message.touch = collision_message.collision_data.touch; + break; } } } @@ -56,9 +70,9 @@ export class CollisionDispatchEngine extends Engine { } ``` -Now we are emitting a BallWallCollisionMessage every time a ball collides with a wall. Why don't you try filling in the other collision messages yourself? +Now we are emitting proper collision messages every time an entity collides with another. -Don't forget to add it in **game.ts** +Don't forget to add our new engine in **game.ts** ```ts world_builder.add_engine(CollisionDispatchEngine); @@ -69,3 +83,5 @@ Clever readers have probably noticed that this is a bit of an awkward structure. What you really want to do, fundamentally, is map two collision types, independent of order, to a message emitting function. You'll probably need to implement a custom data structure to do this cleanly. It's very much outside of the scope of this tutorial for me to do this, but I wish you luck! {{% /notice %}} + +Next, we'll make our game actually do things in response to these messages. diff --git a/content/pong/ball/bouncing/collision_resolution.md b/content/pong/ball/bouncing/collision_resolution.md index 824c42b..23d0661 100644 --- a/content/pong/ball/bouncing/collision_resolution.md +++ b/content/pong/ball/bouncing/collision_resolution.md @@ -88,3 +88,35 @@ export class UpdateVelocityEngine extends ComponentModifier { } } ``` + +Our BallPaddleCollisionEngine will behave the exact same way. Why don't you try to fill it in yourself? + +Finally, we want to make sure our paddles don't go past the game boundary. + +```ts +import { Emits, Engine, Reads } from "encompass-ecs"; +import { BoundingBoxComponent } from "game/components/bounding_box"; +import { PositionComponent } from "game/components/position"; +import { PaddleWallCollisionMessage } from "game/messages/collisions/paddle_wall"; +import { UpdatePositionMessage } from "game/messages/update_position"; + +@Reads(PaddleWallCollisionMessage) +@Emits(UpdatePositionMessage) +export class PaddleWallCollisionEngine extends Engine { + public update() { + for (const message of this.read_messages(PaddleWallCollisionMessage).values()) { + const paddle_position = message.paddle_entity.get_component(PositionComponent); + const paddle_bounding_box = message.paddle_entity.get_component(BoundingBoxComponent); + + const x_distance = Math.abs(message.paddle_new_x - (message.touch.x + paddle_bounding_box.width * 0.5)); + const y_distance = Math.abs(message.paddle_new_y - (message.touch.y + paddle_bounding_box.height * 0.5)); + + const position_message = this.emit_component_message(UpdatePositionMessage, paddle_position); + position_message.x_delta = message.normal.x * x_distance; + position_message.y_delta = message.normal.y * y_distance; + } + } +} +``` + +That's it for defining our collision behavior! diff --git a/content/pong/introduction.md b/content/pong/introduction.md index a1ab61b..3574aef 100644 --- a/content/pong/introduction.md +++ b/content/pong/introduction.md @@ -8,7 +8,7 @@ Everyone has played, or at least heard of, Pong. Right? Right... ![pong](/images/pong.png) -Pong was one of the first video games ever created and as such, it is extremely simple. We're introducing a lot of new concepts with Encompass and the Hyper ECS architecture, so I think it's a good choice to try re-implementing the very simple Pong in Encompass as an example. +Pong was one of the first video games ever created and as such, it is extremely simple. We're introducing a lot of new concepts with Encompass and the Hyper ECS architecture, so I think it's a good choice to try re-implementing this game in Encompass as an example. We'll be developing this with the Encompass/LOVE starter pack. Go ahead and [set that up](/getting_started/case_study_love/) if you haven't already so you can follow along. And please do follow along - you can do it!