What I learned creating a collision engine pt-2.

Alright, so abstraction is an incredibly powerful tool we all should respect what does that look like in code.

Well I had one point of origin I was using for my avatar the bottom left corner, why? :shrugs: Had to start somewhere. So my movement code looked like this.

function moveavatarDown() {  let bottomNumbers = avatar.style.bottom.replace("px", "")  let bottom = parseInt(bottomNumbers, 10)  if (bottom > 0) {  avatar.style.bottom = `${bottom -4}px`  }}function moveavatarLeft() {  let leftNumbers = avatar.style.left.replace("px", "")  let left = parseInt(leftNumbers, 10)  if (left > 0) {  avatar.style.left = `${left -4}px`  }}

You can imagine the changes to go up and right. No? It’s just changing the negatives to positives. A good life skill to have… and yeah flipping the > to ≤ and the following number to match the screen size. So this was the first abstract function I built which had limited use cases. Each boundary has to be hard coded into the if function, and they only work in one direction. Not very dynamic, but it didn’t have to be. The scope of this portion didn’t need any more abstraction because I don’t want the avatar to leave the confines of my screen.

The next step I was working on was making a rule set that was somewhat more abstract for approaching an object. This is probably a good time to stop and talk about an input and output table (IOT). An IOT is a set of inputs you could imagine going into your function and the outputs as something happening as a result those inputs going into your function. This is true for the overarching goal I was trying to reach, but it was also true for every step of the way. The next set of rules I had to create was saying “each side of the avatar, isn’t allowed to go through any side of a solid object, other wise movement’s allowed”. So in the big picture I have an input from the user coming through an event listener, and I have functions that move the avatars position. But I don’t have the avatars sides, or a way to identify solid objects, or a rule set for them. So by using an IOT here I could’ve saved a lot of time in understanding what I missing to make this work. There were certain inputs I need to have to make the output of this “rule”. So if you’re reading this and you’re find you’re frequently lost on what you need to do. Break it down into an IOT.

I still hadn’t learned about an IOT… it took me half a day to realize I needed to define the avatars sides, and that I had to do it at the start of each event. After looking up the various DOM properties I found offsetTop and offsetLeft and my document level event listener got a brand new component!

document.addEventListener("keydown", (event) => {  let avatarLeft = avatar.offsetLeft  let avatarTop = avatar.offsetTop  let avatarRight = (avatar.offsetLeft + 16)  let avatarBottom = (avatar.offsetTop + 16)

Now every time there was a valid key down event my logic tree had access to the avatars current position when the event listener was invoked. Huzzah progress! At this point my approach wasn’t abstract and I only had one object I had added, so I started down a path that lost me about a day of productive work. I defined the boundaries of the object in the function that decided if the avatar got to move or not.

I don’t have the code anymore because of how much I’ve had to rework that function into what it is now, but it was a mess and it was built to work for just the one object. The two short comings of this code was that the object was defined in a hard coded manner inside the function so it had a limitation to how dynamic it could be. And I was running the function based off of whether or not the logic was true or false for the one object. So when I did add another object everything broke.

Coding in a flailing manner feels a lot like being on a roller coaster. It has highs and lows, and when you succeed you feel like a boss! And then you hit your head on a wall and are in the dumps. Learning to slow down. Define your IOT, think about how to get it into the function, and if the function can be broken up more. The above function became much easier when I realized I needed it to return true or false, that was it. I just needed a logic function to return true or false.

function    canAvatarMoveDown(avatarLeft, avatarRight,  avatarBottom){  value = true  objectArray.forEach(object => {    if (Math.abs(avatarBottom - object.top)<4 && (avatarLeft >     object.left && avatarLeft < object.right || avatarRight >   object.left && avatarRight < object.right)){      value = false      return value    }})  return value}

Ignore the forEach and objectArray for now. I haven’t gotten to that part yet. But this is all I needed a function to do. Identify where the avatar existed relative to other objects and return true or false.